删除别名指针



这样做:

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

我假设如果这些类型中的任何一个都有非平凡析构函数,那么这将不起作用,但是这样可以吗?

在任何情况下都不起作用,如果我们假设工作意味着具有良好定义的行为,而不是看起来工作(即不崩溃)

不,无论项是否具有普通析构函数,这都是未定义行为。如果析构函数是微不足道的,它可能看起来"工作",而实际上它正在泄漏内存,等等。

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

5.3.5/2: "在第一个备选项(删除对象)中delete的操作数可以是…指针指向由先前的new-expression创建的非数组对象... .

指针的值在你这样做的时候不会改变,所以这应该像预期的那样工作,提供sizeof(char*) == sizeof(int*)。该特定比较的结果是实现定义的,如果假设为假,则行为是未定义的。

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

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

#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;
}

最新更新