c++ - 在堆栈上使用带有变量的新位置是否正确?
问题描述
让我们看一下这段代码:
A a(123);
new(&a) A(124);
测试表明,在这种情况下,当程序关闭时,析构函数~A()
将被调用一次。因此,如果A
我们有一些指针作为字段,我们将得到内存泄漏。
A a(123);
a.~A();
new(&a) A(124);
在这里一切都会是正确的。但是根据标准在析构函数调用后使用对象是未定义的行为(尽管大多数编译器提供的行为没有一些麻烦)。
我可以获取已调用析构函数的对象的地址吗?在堆栈变量上调用放置新是正确的操作吗?
解决方案
我可以获取已调用析构函数的对象的地址吗?
[编辑:] 这样的地址是有效的,所以如果你有一个指向它的指针,它是有效的。
事后你能知道它的地址吗,我不太确定。
basic.life.6 […] 在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,任何表示对象所在存储位置地址的指针都可以使用,但只能在有限的方式。[…] 这样的指针指的是分配的存储空间,并且像指针是 void* 类型一样使用指针是明确定义的。
查看全文以了解所有限制,但允许在placement-new 中使用。
至于评论,我认为您的两个样本在您展示的范围内都是正确的。
A a(123);
new(&a) A(124);
鉴于我们在样本中所知道的,我认为这是正确的。
根据basic.life.5,通过重新使用对象的存储来结束对象的生命周期是有效的。唯一的条件是程序不依赖于析构函数产生的副作用——为了安全起见,我只会在可简单破坏的类型上这样做。否则,您需要一个显式的析构函数调用,就像您在那里所做的那样:
A a(123);
a.~A();
new(&a) A(124);
我没有看到任何阻止这种情况的规则。该标准甚至明确提到了这种结构何时无效:
如果一个程序:
- 以静态、线程或自动存储持续时间结束 T 类型对象的生命周期
- 当隐式析构函数调用发生时,另一个原始类型的对象不占用相同的存储位置,
程序的行为是未定义的。
(格式化为我的项目符号)
虽然不是一个明确的证据,但这段话表明在其他情况下,行为是有定义的。我想不出他会违反的另一条规则。
(请注意我使用标准的 C++20 版本)
推荐阅读
- android - 如何在 roomdb 查询中使用 where 关键字
- javascript - 删除axios方法返回空数据
- sql - 缺少关键字 oracle SQL 00905
- algorithm - 与起点相比,终点是否距离任意点近 x%
- scheme - 是否有 SICP 练习的风格指南?
- html - 我的 HTML 按钮内的文本超出了按钮
- java - IntelliJ 反编译按钮(将 Kotlin 代码转换为 Java)在哪里?
- javascript - 如何在单击时创建多个输入字段
- python - Matplotlib 3d scatter _facecolors3d 不工作
- gitlab - Gitlab : Peer 的证书颁发者已被用户标记为不信任