C++ 我使用了三种不同的内存清除方法。他们都安全吗?我可以得到内存泄漏吗?

C++ 我使用了三种不同的内存清除方法。他们都安全吗?我可以得到内存泄漏吗?,c++,visual-c++,C++,Visual C++,我使用“placement new”分配对象。我使用了三种不同的内存清除方法。他们都安全吗?我可以得到内存泄漏吗 #include <iostream> #include <exception> #include <vector> using namespace ::std; class A{ private: double x; public: A() : x(0) { cout << "A class; ptr: " <

我使用“placement new”分配对象。我使用了三种不同的内存清除方法。他们都安全吗?我可以得到内存泄漏吗

#include <iostream>
#include <exception>
#include <vector>
using namespace ::std;

class A{
private:
    double x;
public:
    A() : x(0) { cout << "A class; ptr: " << this << " created." << endl; } 
    ~A() { cout << "A class; ptr: " << this << " destroyed." << endl; }
};

int main(int argc, char* argv[])
try{
    // 1. Creating of object in the necessary memory address

    static_assert(sizeof(char) == 1, "Unexpected size of char.");
    int x = -1; // Variants of memory clearing
    while (x < 0 || x > 2) {
        cout << "Variant (0,1,2): ";
        cin >> x;
    }
    char* p = new char[sizeof(A)]; // some memory area...

    A* a = new(p)A(); // Place my object in the 'p' address.

    // Here is my basic work to do...

    // Now I must to free my memory:
    if(!x){ // First variant
        delete a;           
    }
    else if (x == 1){ // Second variant
        delete reinterpret_cast<A*>(p); 
    }
    else if (x == 2){ // Third variant
        a->~A();        
        delete[] p; 
    }
    else{
        throw runtime_error("Invalid variant!");
    }
    a = nullptr;
    p = nullptr;

    cout << endl;   
}
catch(exception& e){
    cerr << e.what() << endl;
    return 1;
}
catch(...){
    cerr << "Unknown exception." << endl;
    return 2;
}
#包括
#包括
#包括
使用namespace::std;
甲级{
私人:
双x;
公众:

A():x(0){cout带有
delete[]
和显式析构函数调用的变量是正确的,因为它反映了您如何分配/构造它:

char* p = new char[sizeof(A)];
A* a = new(p)A();
...
a->~A();        
delete[] p; 
<>但是如果你没有很好的理由使用新的布局,考虑简单明了:

A* a = new A();
...
delete a;
尽管每个
new
都应该调用
delete
,每个
new[]
都应该调用
delete[]
,但由于您分配了一个
char
数组,第二个选项似乎不太合理,但仍然合法(只要您确定内存块的大小确实等于
sizeof(A)
,并且此数组中存在
A
类型的有效对象):


由于标准保证
sizeof(char)
始终返回1。

带有
delete[]
和显式析构函数调用的变量是正确的,因为它反映了您如何分配/构造它:

char* p = new char[sizeof(A)];
A* a = new(p)A();
...
a->~A();        
delete[] p; 
<>但是如果你没有很好的理由使用新的布局,考虑简单明了:

A* a = new A();
...
delete a;
尽管每个
new
都应该调用
delete
,每个
new[]
都应该调用
delete[]
,但由于您分配了一个
char
数组,第二个选项似乎不太合理,但仍然合法(只要您确定内存块的大小确实等于
sizeof(A)
,并且此数组中存在
A
类型的有效对象):


因为标准保证
sizeof(char)
始终返回1。

第三个变量是删除对象并清除已分配内存的正确方法。

第三个变量是删除对象并清除已分配内存的正确方法。

当您的问题简单地重复标题时,通常意味着您描述得不够:p可能是e解释您的三个变体(我知道您的代码很短,但仍然有帮助)永远不要显式调用析构函数!当实例超出范围或调用delete时,将自动调用析构函数。
char
是标准要求的1字节长,断言是多余的。@g-makulik使用placement new时需要调用析构函数。@Bush这本书可能说字节的大小是i实现定义。sizeof(char)在任何情况下都将是1。当你的问题只是重复标题时,通常意味着你描述得不够详细:p也许可以解释你的三个变体(我知道你的代码很短,但仍然有帮助)永远不要显式调用析构函数!当实例超出范围或调用delete时,将自动调用析构函数。
char
是标准要求的1字节长,断言是多余的。@g-makulik使用placement new时需要调用析构函数。@Bush这本书可能说字节的大小是i实现已定义。sizeof(char)在任何情况下都将为1。>避免这样做,只需执行…我知道。我的问题是关于其他。>重要的是要知道,应该为每个新的[]调用delete,为每个新的[]调用delete[]。如果使用new[]然后尝试使用delete释放此内存…我知道。我的指针指向同一内存地址。禁止对同一指针调用delete\delete[]两次。@布什:第二个选项依赖于两个事实:
p
指向的内存块大小等于
sizeof(A)
和2.有效对象存储在此内存中,以便调用相应的析构函数。>避免这样做,只需执行…我知道。我的问题是关于其他。>重要的是要知道,应该为每个新[]调用delete,为每个新[]调用delete[]。如果使用new[]然后尝试使用delete释放此内存…我知道。我的指针指向同一内存地址。禁止对同一指针调用delete\delete[]两次。@布什:第二个选项依赖于两个事实:
p
指向的内存块大小等于
sizeof(A)
和2.有效对象存储在此内存中,以便调用相应的析构函数。