代码之家  ›  专栏  ›  技术社区  ›  alfC

C++ 11中重构C函数输入输出和销毁参数

  •  0
  • alfC  · 技术社区  · 6 年前

    我必须和一些传统的C函数一起工作,像往常一样,有输入、输入输出和输出参数,我想用C++函数把它们包起来。

    (我用过 double 作为这里简单的参数,但是我认为这个问题对于涉及 struct 有很多成员。)

    c函数如下所示:

    void Cfun(double* in_a, double* io_b, double* out_c, double* in_destr_d){}
    

    在文档中,它说第一个参数 a 是一个输入参数, b 是输入输出, c 是输出和 d 返回时将包含未指定(垃圾)值的输入参数。(而且所有指针都必须是非空的,并且只接受一个元素,因此不涉及数组。)

    在C++中显而易见的是,你可以重构。 Cfun 无以下损失:

    double fun0(double a, double& b, double d){
        double c;
        Cfun(const_cast<double*>(&a), &b, &c, &d);
        return c;
    }
    

    这应该行得通,但也会涉及到原始c版本中没有的副本。所以,鉴于我们对 康乐 (文档+我们知道我们在做什么)更好的版本可能是:

    double fun1(double const& a, double& b, double& d){
        double c;
        Cfun(const_cast<double*>(&a), &b, &c, &d);
        return c;
    }
    

    也就是说, 提升为常量引用, D 被提升为推荐人 C 提升为返回值。

    此函数可用于:

    double a = 1.1;
    double b = 1.2;
    double d = 1.3;
    

    i)

    ...
    double c1 = fun1(1.1, b, d); 
    

    二)

    ...
    double c1 = fun1(a  , b, d);
    // b has useful information here
    // d has garbage
    

    第二个和第三个参数必须是l值,这很好。

    不过,参数之间有细微的差别 D . 同时 有有用的信息 D 在函数调用之后使用它的值在任何情况下都是错误的。

    这种情况使我想起了R值引用,并在C++ 11中移动。 其中移动的r值参数最终处于未指定但可分配的状态。 这使我认为C中垃圾参数的输入可以或多或少地映射到R值引用。

    换句话说,可以用这种方式编写包装器来表示 D ,不仅会改变,而且会使其处于不可用状态。

    double fun2(double const& a, double& b, double&& d){
        double c;
        Cfun(const_cast<double*>(&a), &b, &c, &d);
        return c;
    }
    

    这听起来合理吗,我定义这个包装器会丢失一些东西吗?类似的事情是在类似的背景下进行的吗?这是否将r值调整为内置类型(如 双重的 这里)?

    我发现的一个小问题是语法将变得更加冗长,尽管从 D 在函数调用之后。

    据我现在所见,可能的语法变化为:

    i)

    ...
    //  double c = fun2(1.1, b, d); // now compile error, d is not a r-value
    double c = fun2(1.1, b, std::move(d));  
    // obvious error to use the value of d, since it was (probably) moved. However "moving a POD??"
    d = 2.; // assignment is ok
    

    二)

    ...
    double c = fun2(1.1, b, 1.3); // good, I can pass a literal now, nothing to misuse
    

    iii)

    ...
    double c = fun2(1.1, b, double{d}); // not clear, reaction "this seems a redudant cast"
    

    四)

    ...
    double c = fun2(1.1, b, copy(d)); // verbose, but "d should be fine because it was copied"
    

    哪里 template<class T> T copy(T&& t){return t;}

    总之,是 fun2 更好的包装 康乐 fun1 ?

    如果…怎么办 双重的 在上面的所有示例中都被一个包含29个成员变量(并且不想复制它们)的结构替换?

    1 回复  |  直到 6 年前
        1
  •  2
  •   user422005    6 年前

    我的第一反应是C接口似乎指向任意(从接口……未知的长度数组),而当您创建C++接口时,您似乎假定(知道吗?)?)所有参数实际上都是标量?当然,如果真是这样的话,一切都好。

    如果所有参数都是标量的概念都是正确的,我就这么做:

    double fun(double a, double& b, double d);
    

    就这样结束了。