在这种情况下,构造函数Year()是否安全?
struct Year {
int year;
Year(int y) : year(y) {}
Year() { *this = Year(1970); } // *this = this->operator=(Year(1970));
};
Year y;
我想是的,因为一旦执行流程到达构造函数体,就已经用int()初始化了year。还有其他需要考虑的问题吗?
不要考虑其他相同技巧可能导致麻烦的情况。
答案 0 :(得分:5)
当然,this will work,并且有效。
所有数据成员和基础都已在您的ctor-body运行时构建,并且:
[n3290: 12.7/4]
会员功能,包括虚拟功能 (10.3),可以在施工或销毁期间调用(12.6.2)。 [..]
不要混淆:
[n3290: 12.7/1]
对于具有非平凡构造函数的对象,引用任何 构造函数之前的对象的非静态成员或基类 以未定义的行为开始执行结果。
(注意:“在构造函数开始之前”;此子句不适用于此处。)
12.8 "Copying and moving class objects"
中没有任何内容禁止在施工期间进行分配。
请注意,不意味着该对象已开始其“生命周期”:
[n3290: 3.8/1]:
类型为T
的对象的生命周期始于:
- 获得具有
T
类型的正确对齐和大小的存储,并且- 如果对象具有非平凡的初始化,则其初始化完成。
非委派代理人“初始化”的最后一步:
[n3290: 12.6.2/10]:
[..]最后,执行构造函数体的复合语句。
总而言之,这意味着对象的“生命周期”在其最派生的构造函数体已完成执行之前不会开始。
特别是,在对象开始生命之前将指针传递给对象并不是很有用,因为通过该指针执行几乎任何操作都会调用未定义的行为:
[n3290: 3.5/8]:
在对象的生命周期开始之前,但是 在已经分配了对象占用的存储之后 或者,在对象的生命周期结束之后和存储之前 对象占用的是重用或释放的,任何指针 指对象所在或存在的存储位置 可以使用但仅限于有限的方式。 [..]
然而:
[n3290: 3.8/3]:
[..] [注意:[..]另外,一个对象的行为 正在建设和破坏可能不一样 生命周期已开始但未结束的对象的行为。 12.6.2 和12.7描述了施工过程中物体的行为 破坏阶段。 - 后注]
而且,正如我们已经探讨的那样,12.7
请告诉我们,在此阶段的构建过程中,可能会访问
但是你的方法很难遵循;在确定它是有效的之前,我还必须查看上面的段落,所以它显然不是完全直观的。
幸运的是,C ++ 0x引入了构造函数委派,因此您可以编写:
struct Year {
Year() : Year(1970) {}
Year(int y) : year(y) {}
int year;
};
(唉,GCC 4.5.1不支持这一点,所以I cannot demonstrate it to you on ideone.com。事实上,for GCC as a whole there's only a "partial patch" at time of writing。)
答案 1 :(得分:2)
你正在做什么,但是如果你以某种方式递归地调用构造函数那会导致问题,那么什么是行不通的。但是,由于构造函数是在构造了对象的所有非静态数据成员之后调用的,并且this
指针指向可以复制到的有效内存,所以你所做的就好了 - 它是不是标准做法,但没关系。
答案 2 :(得分:0)
这个答案可能是错的;请参阅Tomalak的回答和评论。我会因为历史原因离开它,但你可能在构造函数中调用成员函数。
绝对不是。如果您有任何T*
,请说p
,那么只有在p->
指向某个对象时,您才可以通过p
调用成员函数。但是一个对象只有在构造函数完成时才会开始。因此,当您处于构造函数的中间时,this
不会指向对象!因此,您肯定不会在此非对象上调用任何成员函数,例如赋值运算符。
[Curiosum:在某些情况下, 是合法的delete this;
,你只需要确保析构函数不以任何方式引用this
。在构造函数中将this
传递给其他位置也是可以的,只要它不是 dereferenced ,就像你可以传递任何垃圾指针一样,只要你不这样做使用它。]