问题描述
在以下代码中,是正确创建的返回值。我有一些疑问,因为对构造函数的两个参数都相关。第二个参数使用move是否会破坏第一个参数。或者,如果第一个参数总是在第二个参数之前创建:
class A
{
private:
struct B
{
int a;
string b;
int c;
};
struct C
{
double d;
float f;
};
struct Key
{
int a;
string b;
double d;
};
struct Data
{
B x;
C y;
};
public:
Data data;
using ReturnType = pair<Key,Data>;
ReturnType operator()(Source input)
{
// use input to fill Data
return {{data.x.a,data.x.b,data.y.d},move(this->data)};
}
};
注意:源可以是数据库游标,标准输入流,也可以是包含相关数据的文件指针。
c ++标准是否定义了创建配对的顺序。在这方面,c ++ 11和c ++ 17之间有什么区别。
解决方法
来自this evaluation order reference:
- 在list-initialization中,给定初始化程序子句的每个值计算和副作用在与括号括起来的逗号分隔列表中跟在其后的任何初始化程序子句相关的每个值计算和副作用之前进行排序。
它的意思是在表达式中
{{data.x.a,data.x.b,data.y.d},move(this->data)}
{data.x.a,data.y.d}
部分将先排序(即先评估)move(this->data)
。
n3337,C ++ 11标准草案,包含此段落
[dcl.init.list]
4在大括号的初始列表的初始列表中, 初始化子句,包括任何因扩展包而导致的子句 ([temp.variadic]),按照它们出现的顺序进行评估。 也就是说,与 给定的初始化子句在每次值计算之前进行排序 和随之而来的任何初始化程序子句的副作用 在初始化列表的逗号分隔列表中。 [注意:此 评估顺序成立,无论 初始化;例如,当 初始化列表被解释为构造函数调用的参数, 即使通常情况下, 通话参数。 —尾注]
因此,当使用大括号初始化时,在Key
的参数之前将对在ReturnType
中初始化Data
的参数进行全面评估。
此后,每个C ++标准中都有类似的措辞。