Pot*_*ter 6 c++ destructor undefined-behavior
这是一个糟糕的模式.复制和交换更好.
foo & operator = ( foo const & other ) {
static_assert ( noexcept( new (this) foo() ), "Exception safety violation" );
this-> ~ foo();
try {
new (this) foo( other );
} catch (...) {
new (this) foo(); // does not throw
throw;
}
return * this;
}
Run Code Online (Sandbox Code Playgroud)
只要foo是不多态性,有什么可以去错了吗?(但是,假设它是基类.)
背景:我正在处理本地存储类型擦除,另一种方法是swap通过本地存储空间实现两个硬编码分配.源和目标的内存blob中的对象具有不同的类型,并且根本无法相互交换.根据这种交换定义的复制/移动构造是看似没有收益的两倍.
销毁并重新生成与复制并交换具有根本不同的行为。比较:
复制和交换:
两者都有其优点,但复制和交换无处不在,因此它的缺点是按照最小意外原则提出的。那么让我们模拟一下它的行为:
foo & operator = ( foo const & other ) {
static_assert ( std::is_nothrow_move_constructible< foo >::value
|| std::is_nothrow_default_constructible< foo >::value
, "Exception safety violation" );
foo next( other );
try {
this-> ~ foo();
new (this) foo( std::move( next ) );
} catch (...) {
new (this) foo();
throw;
}
return * this;
}
Run Code Online (Sandbox Code Playgroud)
虽然更复杂,但这比 throwing 表现得更好swap,因为 throwing 可能会在异常后留下旧值和新值的大杂烩。
在移动构造函数不抛出异常的常见情况下(您记得声明它noexcept,对吧?),该算法可以很好地简化:
foo & operator = ( foo const & other ) {
foo next( other );
// The dangerous part is over now.
this-> ~ foo();
new (this) foo( std::move( next ) );
return * this;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
151 次 |
| 最近记录: |