Ctor Initializer:自我初始化导致崩溃?

Abh*_*hay 2 c++ constructor ctor-initializer

我很难调试生产崩溃.只是想与这里的人们确认语义.我们有一个类......

class Test {
public:
  Test()
  {
    // members initialized ...
    m_str = m_str;
  }
  ~Test() {}
private:
  // other members ...
  std::string m_str;
};
Run Code Online (Sandbox Code Playgroud)

有人改变了初始化以使用ctor初始化列表,这在我们的代码语义中是合理正确的.初始化顺序及其初始值是正确的.所以班级看起来像......

class Test {
public:
  Test() 
    : /*other inits ,,, */ m_str(m_str)
  {
  }
  ~Test() {}
private:
  // other members ...
  std::string m_str;
};
Run Code Online (Sandbox Code Playgroud)

但是代码突然崩溃了!我在这段代码中分隔了很长的列表m_str(m_str).我通过链接文本证实了这一点.

它必须崩溃吗?标准对此有何看法?(这是不确定的行为吗?)

Pét*_*rök 13

第一个构造函数相当于

  Test()
  : m_str()
  {
    // members initialized ...
    m_str = m_str;
  }
Run Code Online (Sandbox Code Playgroud)

也就是说,当你在构造函数中进行赋值时,m_str 已经被隐式初始化为空字符串.因此,对自我的赋值虽然完全没有意义且多余,但不会产生任何问题(因为std::string::operator=()任何编写好的赋值运算符都应该检查自我赋值,在这种情况下什么都不做).

但是,在第二个构造函数中,您尝试m_str在初始化列表中初始化 - 此时它尚未初始化.所以结果是未定义的行为.

更新:对于原始类型,这仍然是未定义的行为(导致具有垃圾值的字段),但它不会崩溃(通常 - 请参阅下面的异常注释),因为原始类型根据定义没有构造函数,析构函数并且不包含指针到其他对象.

对于任何不包含具有所有权语义的指针成员的类型也是如此.std::string特此证明不是其中之一:-)

  • 取决于"原始类型"的含义.即使将不确定值赋值给`int`原则上也会导致崩溃,因为标准允许填充和陷阱表示`int`.您必须使用`char`类型来获得具有定义良好的初始化的可移植代码. (2认同)