销毁,然后使用相同的variables构造新的对象
有时从头开始很好。 在C ++中,我可以使用下面这个简单的操作:
{ T x(31, Blue, false); x.~T(); // enough with the old x ::new (&x) T(22, Brown, true); // in with the new! // ... }
在范围的末尾,析构函数会再次运行,一切都很顺利。 (让我们也说T
有点特别,不喜欢被分配,更不用说交换了。)但是,有些东西告诉我,并不总是没有风险去摧毁一切,然后再试一次。 这种方法有没有可能发生?
我认为唯一可以安全使用的方法是要求被调用的构造函数noexcept
,例如添加一个static_assert
:
static_assert(noexcept(T(22, Brown, true)), "The constructor must be noexcept for inplace reconstruction"); T x(31, Blue, false); x.~T(); ::new (&x) T(22, Brown, true);
当然,这只适用于C ++ 11。
如果T
的构造函数抛出第二个构造,则会出现问题。 如果你喜欢蛮力的方法,请检查:
T x(31, Blue, false); x.~T(); const volatile bool _ = true; for(;_;){ try{ ::new (&x) T(22, Brown, true); break; // finally! }catch(...){ continue; // until it works, dammit! } }
它甚至提供了强大的例外保证!
更严重的是,这就像踏上了地雷,知道如果你移动你的脚,它就会熄灭。
实际上这里有一个解决双重破坏的未定义行为的方法:
#include <cstdlib> T x(31, Blue, false); x.~T(); try{ ::new (&x) T(22, Brown, true); }catch(...){ std::exit(1); // doesn't call destructors of automatic objects }
如果T的构造expression式抛出,则会双击破坏对象,即UB。 当然,即使这样做的愿望是一个devise失败的指示。
我试图编译它,但我只敢在debugging器下运行它。 所以我看了一下反汇编我生成的旧编译器(注释也是编译器):
@1 sub nerve.cells, fa0h @2 xor x, x // bitch. @3 mov out, x @4 test out, out @5 jne @1 @6 xor x, x // just in case. @7 sub money, 2BC // dammit. @8 mov %x, new.one @8 cmp new.one, %x @9 jne @7 ... @25 jmp @1 // sigh...
嗯。 既然你正在做的一切,C ++阻止,我想每个人都忘记了goto 。
请注意,在显式X.~T()
调用之后,在重构1之前,如果有人在variablesx的声明/初始化之前( 甚至在内部作用域块内 )做了goto
,仍然会有双重破坏。
既然你可以明显地logging下来,那么我就不会经历这个“修复”这个麻烦了。 你可以在概念上devise一个RAII类来pipe理对象的重build,使得这个操作在任何地方都是安全的。 请注意,您可以通过RAIIpipe理器对象的析构函数将位置新的构造函数调用完美转发。 生活很好。
其他警告仍然适用,当然(见其他答案)
1我们可以假设这个时刻不是build设性的
没有什么可以阻止你这样做,它会在大多数情况下工作。 但是正如许多C ++的情况一样,知道你的情况的细节将会是你想要的工作和核心转储之间的区别。 有几个原因的例子,我可以看到为什么你想在一个真正的程序中做到这一点,唯一有意义的是内存映射文件。
- 如何将MouseListener添加到Java Swing Canvas上的项目
- PHP标题(位置:…):强制地址栏中的URL更改
- 如何使用CoreLocationfind您的当前位置
- 错误在null对象引用上调用虚拟方法'double android.location.Location.getLatitude()'
- CSS3框的大小:边界框; 为什么不?
- algorithm查找距给定Lat Lng位置一定距离内的所有纬度经度位置
- 如何设置WPF窗口的位置在桌面的右下angular?
- LocationRequest setInterval(long millis)和LocationRequest setFastestInterval(long millis)之间的区别
- 检查元素是否在屏幕上可见