C++ 我可以在构造函数的主体中进行构造吗? 让我们考虑在一个类的构造函数 s/COD>的执行过程中,似乎可以使用另一个构造函数构造 s>代码>。一种解决方案可以是在此处重新放置一个位置,以重用存储: struct S{ unsigned int j; //no const neither reference non static members S(unsigned int i){/*...*/} S(int i){ if (i>=0) { new (this) S(static_cast<unsigned int>(i)); return;} /*...*/ } }; int i=10; S x{i};//is it UB? 结构{ unsigned int j;//无常量也不引用非静态成员 S(无符号整数i){/*…*/} S(国际一级){ 如果(i>=0){ 新(本)S(静态_cast(i)); 返回;} /*...*/ } }; int i=10; sx{i}//是UB吗?

C++ 我可以在构造函数的主体中进行构造吗? 让我们考虑在一个类的构造函数 s/COD>的执行过程中,似乎可以使用另一个构造函数构造 s>代码>。一种解决方案可以是在此处重新放置一个位置,以重用存储: struct S{ unsigned int j; //no const neither reference non static members S(unsigned int i){/*...*/} S(int i){ if (i>=0) { new (this) S(static_cast<unsigned int>(i)); return;} /*...*/ } }; int i=10; S x{i};//is it UB? 结构{ unsigned int j;//无常量也不引用非静态成员 S(无符号整数i){/*…*/} S(国际一级){ 如果(i>=0){ 新(本)S(静态_cast(i)); 返回;} /*...*/ } }; int i=10; sx{i}//是UB吗?,c++,constructor,language-lawyer,C++,Constructor,Language Lawyer,中定义了存储重用。我不知道在构造函数执行期间(重新)使用存储时如何阅读本节 是UB吗 不,不是[basic.life]/5说: 程序可以通过重用对象占用的存储来结束任何对象的生命周期,或者通过使用非平凡析构函数显式调用类类型对象的析构函数来结束任何对象的生命周期。对于具有非平凡析构函数的类类型的对象,在重用或释放该对象占用的存储之前,程序不需要显式调用析构函数;但是,如果没有显式调用析构函数,或者如果没有使用删除表达式来释放存储,则不应隐式调用析构函数,并且依赖于析构函数产生的副作用的任何程序都

中定义了存储重用。我不知道在构造函数执行期间(重新)使用存储时如何阅读本节

是UB吗

不,不是<代码>[basic.life]/5说:

程序可以通过重用对象占用的存储来结束任何对象的生命周期,或者通过使用非平凡析构函数显式调用类类型对象的析构函数来结束任何对象的生命周期。对于具有非平凡析构函数的类类型的对象,在重用或释放该对象占用的存储之前,程序不需要显式调用析构函数;但是,如果没有显式调用析构函数,或者如果没有使用删除表达式来释放存储,则不应隐式调用析构函数,并且依赖于析构函数产生的副作用的任何程序都具有未定义的行为


重点放在与类相关的部分,它有一个平凡的析构函数。关于具体的
new(this)T表单中,我在
[class.cdtor]
[class.dtor]
中未发现此规则的例外情况。在这种情况下,标准完全没有规定,我找不到相关的CWG问题

就其本身而言,您的位置不是新的。毕竟,您有没有对象的存储,所以您可以直接在其中构造对象。正如您所说的,第一个对象的生存期尚未开始

但现在的问题是:原始对象会发生什么?因为通常,构造函数只在没有对象的存储上调用,构造函数的结束标志着对象生命周期的开始。但现在已经有另一个对象了。新物体被摧毁了吗?它没有效果吗

该标准在[class.cdtor]中缺少一段,该段说明了如果在正在构建和销毁的对象的存储中创建了新对象,会发生什么

您甚至可以构造更奇怪的代码:

struct X {
  X *object;
  int var;
  X() : object(new (this) X(4)), var(5) {} // ?!?
  X(int x) : var(x) {}
} x;

使用委托构造函数和/或工厂?@Jarod42问题是这些都是无条件的。OP试图根据运行时参数值仅委派部分时间。@Angew
S(int i):S(make(i)){}
使用移动构造函数(或完全省略:-)。构造函数将是它的错误位置(当在运行时完成时),因此如果(i>=0)j=static\u cast(i),则必须使用类似工厂的方法
;else j=..
也许?另外,请注意,该类不必有一个平凡的析构函数(您在析构函数上说“emphasis”,但似乎强调了另一部分?@raket1111,我的意思是,“或者通过显式调用具有非平凡析构函数的类类型的对象的析构函数。”与OP无关,因为
S
有一个微不足道的析构函数。我的问题是结束生存期,因为根据[basic.life]/1.2,类型为T的对象的生存期开始于:如果对象具有非真空初始化,则其初始化完成。所以我们不能结束生命,因为它还没有开始。