相关疑难解决方法(0)

是`new(this)MyClass();`直接调用析构函数后的未定义行为?

在我的这个问题中,@ DeadMG说通过this指针重新初始化类是未定义的行为.标准中有没有提到它?

例:

#include <iostream>

class X{
  int _i;
public:  
  X() : _i(0) { std::cout << "X()\n"; }
  X(int i) : _i(i) { std::cout << "X(int)\n"; }

  ~X(){ std::cout << "~X()\n"; }

  void foo(){
    this->~X();
    new (this) X(5);
  }

  void print_i(){
    std::cout << _i << "\n";
  }
};

int main(){
  X x;
  x.foo();
  // mock random stack noise
  int noise[20];
  x.print_i();
}
Run Code Online (Sandbox Code Playgroud)

Ideone的输出示例(我知道UB也可能是"看似正确的行为").
请注意,我没有在类之外调用析构函数,因为没有访问生命周期结束的对象.另请注意,@ DeadMG表示直接调用析构函数是可以的 - 因为它为每个构造函数调用一次.

c++ this placement-new undefined-behavior

9
推荐指数
1
解决办法
575
查看次数

通过在此指针上放置new来重新初始化对象时的未定义行为

我看到了关于Piotr Padlewski的cppcon的演示文稿,说明以下是未定义的行为:

int test(Base* a){
  int sum = 0;
  sum += a->foo();
  sum += a->foo();
  return sum;
}

int Base::foo(){
  new (this) Derived;
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

注意:假设sizeof(Base) == sizeof(Derived)并且foo是虚拟的.

显然这很糟糕,但我很感兴趣为什么它是UB.我确实理解UB访问realloced指针,但他说,这是相同的.

相关问题:`new(this)MyClass();`直接调用析构函数后的未定义行为?在哪里说"ok,如果没有例外" 是否有效直接调用(虚拟)析构函数?它说的new (this) MyClass();结果是UB.(与上述问题相反)

C++使用放置新的未定义行为构造对象两次?它说:

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

这听起来好像没问题.

我在Placement new中找到了另一个新的贴图描述,并使用const成员分配了类

如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,则在原始对象占用的存储位置创建新对象,指向原始对象的指针,引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以用来操纵新对象,如果:

  • 新对象的存储完全覆盖原始对象占用的存储位置,以及

  • 新对象与原始对象的类型相同(忽略顶级cv限定符),和

  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定的非静态数据成员或引用类型,以及

  • 原始对象是类型为T的派生程度最高的对象,新对象是类型为T的派生程度最高的对象(也就是说,它们不是基类子对象).

这似乎解释了UB.但这是真的吗?

这是不是意味着,我不能拥有std::vector<Base>?因为我假设由于它的预分配std::vector必须依赖placement-news和显式ctors.第4点要求它是最衍生的类型,Base显然不是.

c++ destructor placement-new language-lawyer

7
推荐指数
1
解决办法
306
查看次数

手动对象构造函数调用

你能否告诉我是否可以手动调用对象构造函数?我知道这是错的,我不会在我自己的代码中做类似的事情,我知道我可以通过创建和调用初始化函数来解决这个问题,但问题是我偶然发现了一个存在数千行代码的情况.对象及其父母的构造者......

class MyClass()
{
    MyClass() { }
    virtual ~MyClass();

    void reset()
    {
         this->~MyClass();
         this->MyClass::MyClass(); //error: Invalid use of MyClass
    }
};
Run Code Online (Sandbox Code Playgroud)

c++ gcc constructor class visual-c++

4
推荐指数
1
解决办法
2178
查看次数