2011-09-23 144 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; 

}