我必须和一些传统的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个成员变量(并且不想复制它们)的结构替换?