销毁C++中动态分配的内存(数组对象)



下面你会发现一个代码(编译/运行(,简而言之,它调用了一个在堆上动态分配数组的函数。

#include "stdafx.h"
#include <stdio.h>
class A
{
public:
A()
{
printf ( "constructor has been called !!! n" );
}
~A()
{
printf ( "destructor has been called !!! n" );
}
char* f( void )
{
//char *data_raw = NULL;
data_raw = NULL;
data_raw = new char [ 20 ];
for( int i = 0; i < 20; i++ )
{
data_raw[ i ] = '0';    
}
data_raw[  0 ] = 'h';
data_raw[  1 ] = 'e';
data_raw[  2 ] = 'l';
data_raw[  3 ] = 'l';
data_raw[  4 ] = 'o';
data_raw[  5 ] = ' ';
data_raw[  6 ] = 'w';
data_raw[  7 ] = 'o';
data_raw[  8 ] = 'r';
data_raw[  9 ] = 'l';
data_raw[ 10 ] = 'd';
data_raw[ 11 ] = '!';
return data_raw;
} //data raw ptr-var is destroyed
private:
char *data_raw;
};

int  _tmain( int argc, _TCHAR* argv[] )
{
char *data = NULL;
printf( "data: %c", data );
A a;
data = a.f();
delete [] data;  
return 0;
}

我的问题:

1( 关于销毁动态分配的内存,我应该使用 delete 还是 delete [ ] ?他们都编译...

2(当我使用前者(删除(时,类析构函数被调用,但当我使用删除[]时不会?

永远不应该使用像A这样的类,尤其是你使用它的方式。

具体说来:

  • 不应在保留指向拥有对象的指针时转移内存的所有权(除非它是弱引用(。这几乎总是意味着您正在做出指针有效的无效假设,尽管事实上内存很容易在使用非拥有指针之前很久就被释放。
  • 除非在非常特殊的情况下,否则不应直接分配和释放内存。使用现有的容器类,或者如果没有合适的容器类,请根据需要使用智能指针 -std::unique_ptrstd::shared_ptrstd::weak_ptr
  • 不应将指针传递到分配的内存,其中分配的数量(或分配数量的下限(对新所有者来说是不熟悉的。将引用传递给正确的对象,或使用移动语义传递容器,或者传递跨度。请注意,当您只是传递值(由于复制省略号(时,可能会发生这种情况。
  • 通常,您应该倾向于保留创建者对象的内存所有权,允许非所有权访问权限,并让创建者对象销毁它创建的内容。

您的代码不遵循这些准则!这太可怕了,太危险了!

我会重写你的代码以遵循你的指导方针,但由于不清楚为什么你甚至需要方法 f 或类 A,我最终只会得到:

#include <iostream>
#include <string>
std::string A_f() { return "hello world"; }
int main( int argc, const char* argv[] )
{
std::cout << A_f();
}

或者只是

#include <iostream>
int main( int argc, const char* argv[] )
{
std::cout << "hello world";
}
当您使用new

初始化堆中的数组时调用delete[],在使用new初始化堆中的对象时使用delete

附带说明一下,我建议您按其所有者删除类的成员。 如果你在这里做你做的事情,你会自找很多麻烦。 删除 A 之外的数组。

对于此示例,没有什么可以阻止您在类 A 的析构函数中调用delete[] data_raw.无需从 A 外部访问它,甚至无需返回指向数组的指针。

class A
{
public:
A()
{
printf ( "constructor has been called !!! n" );
data_raw = NULL;
data_raw = new char [ 20 ];
//....rest ofthe code from f( void )
//....no need to return data_raw        
}
~A()
{
printf ( "destructor has been called !!! n" );
delete [] data_raw; 
}
private:
char *data_raw;
};

最新更新