我有一个Parent类,它接受两个引用可能实际上也可能不实际引用同一个东西。在这种情况下,当它们相同时,我在Child类的初始化列表中得到一个序列点警告:
class A
{
public:
A(int) {}
private:
A() {}
};
class Parent
{
public:
Parent(A&, A&) {}
};
class Child : public Parent
{
public:
Child() :
Parent(
*(_A = new A(0)),
*(_A)) //Warning on this line
{
}
private:
A *_A;
};
int main(int argc, char** argv)
{
return 0;
}
我猜这是因为在分配内存后不能保证在该行上取消引用。无论如何,我的问题是,在没有对父母或A进行更改的情况下,是否存在此问题?
答案 0 :(得分:4)
你是对的,不能保证调用父构造函数的两个参数的顺序(它们之间没有序列点),因此编译器可以在评估{{1}之前合法地评估*(_A)
}}
您是否需要动态分配*(_A = new A(0))
?如果没有,你可以这样做:
A
有一点需要注意,虽然获取成员的地址或对其进行引用是有效的,但使用在class Child : public Parent
{
public:
Child() : Parent( _a, _a ), _a(0) {}
private:
A _a; // _A is reserved for the implementation (compiler + library)
};
成员之前引用或指针是未定义的行为已初始化,只有在_a
构造函数完成后才会发生。也就是说,只要Parent
的构造函数只存储引用但不使用对象就是安全的(沿着刀片的边缘骑行,但没有出血)。
如果Parent
构造函数使用引用而不是存储它,则可以更改Parent
类以接收指向已构造的Child
对象的指针:
A