2011-09-23 137 views
3

这样做:删除别名指针

union{ 
    int * integer; 
    char * character; 
} u; 
u.integer = new int; 
delete u.character; 

u.integer = new int[5]; 
delete [] u.character; 

我认为如果有这些类型的具有不平凡的析构函数这是行不通的,但是这行吗?

+1

这里有一个密切相关的问题:http://stackoverflow.com/q/2140319/57428 – sharptooth

回答

8

这不会在任何情况下都不工作,如果我们假设有良好定义的行为,而不是出现工作工作的方式(即不崩溃)

+0

对我来说够好。谢谢。 – zounds

+0

它确实不够好;我可以回答说:“它会一直工作,并且定义完美”,你无法选择哪个是正确的。 –

1

不,这是不确定的行为,无论是否或者不是该项目有一个微不足道的析构函数。如果析构函数是微不足道的,它可能出现“工作”,实际上它正在泄漏内存等。

+0

它甚至可能不会泄漏内存......它只是未定义:) –

1

我要说这是介于实现定义和未定义之间的某处。

5.3.5/2:“在第一个替代(删除对象)时, 操作数的删除的值可以是...的指针由先前新 - 创建的 非数组对象表达......。

使用你这样做的方式,当指针的值不会改变,所以这应该按预期工作,提供sizeof(char*) == sizeof(int*)。是实现定义特定的比较的结果,如果假设是错误的,那么行为是不确定的。

所以它真的不是特别安全。

0

很容易看出这是一个危险的错误。这两种类型可能具有完全不同且不兼容的内存分配和重新分配方式。这包括填充,垃圾收集,簿记,特定于类的内存操作等。不要这样做。

#include <cstddef> 
#include <cstdlib> 
#include <iostream> 

using namespace std; 

class A 
{ 

    public: 

     void* operator new (size_t size) 
     { 
      cout << "A::operator new (size_t)" << endl; 
      return malloc(size); 
     } 

     void* operator new [] (size_t size) 
     { 
      cout << "A::operator new [] (size_t)" << endl; 
      return malloc(size); 
     } 

     void operator delete (void* ptr) 
     { 
      cout << "A::operator delete (void*)" << endl; 
      free(ptr); 
     } 

     void operator delete [] (void* ptr) 
     { 
      cout << "A::operator delete [] (void*)" << endl; 
      free(ptr); 
     } 

}; 

class B 
{ 

    public: 

     void* operator new (size_t size) 
     { 
      cout << "B::operator new (size_t) with some B-specific stuff" << endl; 
      return malloc(size); 
     } 

     void* operator new [] (size_t size) 
     { 
      cout << "B::operator new [] (size_t) with some B-specific stuff" << endl; 
      return malloc(size); 
     } 

     void operator delete (void* ptr) 
     { 
      cout << "B::operator delete (void*) with some B-specific stuff" << endl; 
      free(ptr); 
     } 

     void operator delete [] (void* ptr) 
     { 
      cout << "B::operator delete [] (void*) with some B-specific stuff" << endl; 
      free(ptr); 
     } 

}; 


int main (int, char**) 
{ 

    union{ 
     A* a; 
     B* b; 
    } u; 

    u.a = new A(); 
    delete u.b; 

    u.a = new A[5]; 
    delete [] u.b; 

}