由于内存重用不当而导致的未定义行为
Undefined behavior caused by not proper memory reusing
标准引用了以下示例(3.8/7 N3797):
struct C
{
int i;
void f();
const C& operator=( const C& );
};
const C& C::operator=( const C& other)
{
if ( this != &other )
{
this->~C(); // lifetime of *this ends
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
C c1;
C c2;
c1 = c2; // well-defined
c1.f(); // well-defined; c1 refers to a new object of type C
如果我们按如下方式实现operator=
,是否存在UB:
const C& C::operator=( const C& other)
{
if ( this != &other )
{ // Note that there is no more explcicitly destructor call,
// since at the time of memory reusing the lifetime of
// this is still going on
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
相关报价为:
如果,在对象的生存期结束后和存储前被占用的对象被重用或释放,则新对象在原始对象占用的存储位置创建指向原始对象的指针,引用到原始对象,或者原始对象的名称将自动引用新对象,并且在新对象已经启动,可以用来操作新对象
没有规则适用于:"在对象占用的存储位置创建新对象"。同时,我们为const
对象提供了一个合适的规则。很明显:
第3.8/9节:
在const对象所在的存储位置创建一个新对象静态、线程或自动存储持续时间占用,或者,在此类const对象在其生命周期结束会导致未定义的行为。
相关规则如下:
3.8/4程序可以通过重用对象占用的存储或通过显式调用具有非平凡析构函数的类类型对象的析构函数。对于对象对于具有非平凡析构函数的类类型,程序不需要显式调用析构函数在对象所占用的存储器被重新使用或释放之前;但是,如果没有明确调用析构函数,如果删除表达式(5.3.5)未用于释放存储,则析构函数不应隐式调用,并且任何依赖于析构函数产生的副作用的程序都未定义行为
您编写的示例是合法的,因为C
有一个琐碎的析构函数。
相关文章:
- 编译C++时未定义的引用
- 引用释放的内存是未定义的行为吗?
- FBString 的小字符串优化是否依赖于未定义的行为?
- C++:为什么这段代码给我内存问题/未定义的行为?
- g++ 未定义的引用,尽管符号存在于 *.so 文件中
- C++动态变量和未定义内存之间的差异
- 在C++中,返回从本地字符数组创建的字符串是否会导致内存泄漏或未定义的行为
- 链接自身依赖于静态库的静态库时未定义的引用
- 自定义强制转换未应用于派生类的引用
- 'std::string::c_str()'如何返回不会导致内存泄漏或未定义的 C 字符串内容的 C 字符串?
- 此代码是否依赖于函数调用顺序未定义的行为
- Visual Studio 2008,检测内存泄漏,符号"__FILE__"未定义
- 依赖于实现的行为和未定义的行为之间有什么区别吗
- 由于内存重用不当而导致的未定义行为
- 为什么传递特征表达式的临时性会导致访问未定义的内存
- 未对齐内存访问:它是定义的行为或不
- 是指向无效内存时sizeof(*ptr)未定义的行为
- 使用已定义结构体的vector到达未初始化内存
- 是什么原因导致了此内存访问错误(C++)?可能是未定义的行为
- c++析构函数和内存分配,以及未定义的行为