gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 18:36:33 24 4
gpt4 key购买 nike

我看到了关于 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;
}

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

显然这很糟糕,但我很想知道为什么它是 UB。我确实了解 UB 访问 realloc ed 指针,但他说,这是一样的。

相关问题:Is `new (this) MyClass();` undefined behaviour after directly calling the destructor?它说“如果没有异常(exception)就可以” Is it valid to directly call a (virtual) destructor?哪里写着 new (this) MyClass();结果在 UB。 (与上述问题相反)

C++ Is constructing object twice using placement new undefined behaviour?它说:

A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

这又听起来没问题。

我在 Placement new and assignment of class with const member 中找到了关于新展示位置的另一个描述

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:

  • the storage for the new object exactly overlays the storage location which the original object occupied, and

  • the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and

  • the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and

  • the original object was a most derived object of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).

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

这是否意味着我不能拥有 std::vector<Base> ?因为我假设由于它的预分配 std::vector一定要靠placement-new s 和明确的 Actor 。第 4 点要求它是派生最多的类型 Base显然不是。

最佳答案

我相信 Elizabeth Barret Browning 说得最好。让我数一数。

  1. 如果 Base 不是可以轻易破坏的,我们就无法清理资源。
  2. 如果sizeof(Derived) 大于this 的动态类型的大小,我们将破坏其他内存。
  3. 如果 Base 不是 Derived 的第一个子对象,那么新对象的存储不会完全覆盖原始存储,您也将结束破坏其他内存。
  4. 如果 Derived 只是与初始动态类型不同的类型,即使它的大小与我们在 cannot be used 上调用 foo() 的对象相同引用新对象。如果 BaseDerived 的任何成员是 const 限定的或者是引用,情况也是如此。您需要std::launder任何外部指针/引用。

然而,如果 sizeof(Base) == sizeof(Derived),并且 Derived 是微不足道的可破坏的,Base 是第一个子对象Derived,而您实际上只有 Derived 对象……这很好。

关于c++ - 通过在此指针上放置 new 重新初始化对象的未定义行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48707481/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com