我想知道这样的构造(初始化列表)是否有明确定义的EO(评估顺序):
struct MemoryManager
{
Pair* firstPair_;//<-beg
Pair* currentPair_;
Pair* lastPair_;//<-end
MemoryManager():lastPair_(currentPair_ = firstPair_ = nullptr)
{/*e.b.*/}
};
如果是的话,我个人更喜欢这种传统方式:
MemoryManager():firstPair_(nullptr),
currentPair_(nullptr),
lastPair_(nullptr)
{/*e.b*/}
答案 0 :(得分:4)
正如约翰·迪布林所说,你的构造在技术上对于给定的具体例子是正确的,但是它很脆弱,并且对很多程序员来说很难理解。
脆性:
如果声明顺序发生变化,可能会失败。
如果更改了初始列表,则会失败。
要自己评估这样的结构,请记住这个想法:代码不是指示编译器进行出价,而是将意图传达给他人(也许是你以后的自己)。
因此,请尝试编写 clear 代码。
干杯&amp;第h。,
答案 1 :(得分:1)
是即可。如您的代码所示,成员将按照它们在struct / class definition 中声明的相同顺序进行初始化(构造函数定义中初始化程序的顺序无关紧要,最多会出现警告告诉你他们的订单不正确)。
12.6.2§5:然后,非静态数据成员应按照在类定义中声明的顺序进行初始化(同样不管mem-initializers的顺序如何)。
请注意,这仅适用于属于同一访问说明符的变量,因此在 public:
说明符中找到的实例变量可以在private:
中找到的变量之前或之后初始化}说明符(当然,struct
计为public:
说明符。)
9.2§12:声明没有插入访问说明符的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。由access-specifier分隔的非静态数据成员的分配顺序未指定(class.access.spec)。
然而,更传统的方式有理由存在,即如果变量声明的顺序发生变化(例如,由于重构),代码将不会无声地破坏。人们不容易认为声明的顺序是相关的,除非警告另有说明。
答案 2 :(得分:1)
如果你想这样做,那就按照每个人立即理解的方式进行,而不必浏览标准:
MemoryManager()
// no initialization here
{
lastPair_ = currentPair_ = firstPair_ = nullptr;
}
但是,我真的没有看到这会给你买什么
MemoryManager()
: lastPair_(), currentPair_(), firstPair_()
{}
只有大约六个字符完全相同。
答案 3 :(得分:0)
对于此特定示例,成员的初始化顺序无关紧要。以下构造函数与问题中的构造函数具有相同的行为:
MemoryManager():firstPair_(lastPair_ = currentPair_ = nullptr)
{/*e.b.*/}
这是因为成员是POD,因此根本没有构造函数默认初始化(12.6.2 / 4 C ++ '03):
如果给定的非静态数据成员或基类没有由mem-initializer-id命名(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer),那么
- 如果实体是(可能是cv限定的)类类型(或其数组)或基类的非静态数据成员,并且实体类是非POD类,则该实体是默认初始化的(8.5) 。如果实体是const限定类型的非静态数据成员,则实体类应具有用户声明的默认构造函数。
- 否则,实体未初始化。如果实体是const限定类型或引用类型,或者是(可能是cv限定的)POD类类型(或其数组)包含(直接或间接)const限定类型的成员,则该程序是错误的形成。
对于上面的原始指针成员,“其他”子弹适用。
现在,即使成员确实有类型,请说:
class MbrType {
public:
MbrType();
MbrType(int *);
MbrType(MbrType const &);
MbrType & operator=(MbrType const &);
};
然后,编写它的构造函数将导致成员具有您期望的值,但是允许非优化编译器将构造函数实现为:
MemoryManager()
: firstPair_ () // implicit call to default constructor
, currentPair_ () // implicit call to default constructor
, lastPair_(currentPair_.operator=(firstPair_.operator=(MbrType (nullptr))))
{/*e.b.*/}
导致6次通话而不是3次。
答案 4 :(得分:-1)
否,但没关系。您的代码不依赖于currentPair_
和firstPair_
归零的顺序。