下面你会发现一个代码(编译/运行(,简而言之,它调用了一个在堆上动态分配数组的函数。
#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_ptr
、std::shared_ptr
和std::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;
};