不需要动态内存分配的话就不需要显示定义析构函数,复制构造函数,赋值操作符,为什么?

为什么动态分配就得显示的定义他们?

这个问题掌握了,你就对C++掌握六成以上了。

当类的构造函数中动态申请了内存的话,如果new 出该类的一个对象,当你delete对象的时候,只能释放掉该类中的其他成员变量,而动态申请的内存空间就无法释放了,这样就会导致内存泄露。所以在构造函数中动态申请了内存的话,那么就一定要在析构函数中用delete运算符来释放申请的内存。

另外,我们知道,如果不显示定义类的复制构造函数、赋值函数的时候,类会产生默认的复制构造函数、赋值函数,而这些默认的函数,只是一种“浅”赋值、“浅”复制。说他们“浅”,是因为他们只是简单的进行赋值和复制,而这样可能会导致这样一种问题。
比如,类的对象A里面有个指针成员变量p,指向一片动态申请的内存区域,当进行对象复制的时候,对象B里面的指针变量将会得到和A里的指针一样的地址值,即他们指向同一块区域。这时如果,对象A中指针p指向的内存空间被释放,那么对象B中的指针指向的位置也一同被释放(因为他们指向同一片内存空间),所以程序就会出错。同理赋值函数也是一样的道理。

这时就该显示的定义类的复制构造函数,赋值操作符,进行深赋值、深复制,来避免上面的问题。追问

那为什么如果不用new,直接申明的时候用char ch[40]这种类似的方法就不用显式定义了?
另外,我想问一下,这两种方法的优劣,以及如何选择什么情况下使用哪一个方法?

追答

问题的关键是:你是否在类的构造函数里动态申请了内存。而不是说你如何定义了类对象(是new出来的还是直接定义)。只要在类的构造函数里动态申请了内存,就必须显示定义析构函数,复制构造函数,赋值操作符,用来解决我上面说的问题,不管你是直接定义了类对象,还是使用new操作符动态申请的内存。

追问

为什么申明的时候用char ch[40]这种类似的方法就不用显式定义析构函数,复制构造函数,赋值操作符了?

两种方法的优劣能说一下吗?

追答

char ch[40];//注意,char 本来就是基本类型,谈不上析构函数,复制构造函数,赋值操作符

你的意思我明白,请你好好看看我上面的回答。
再给你看个例子:
class A
{
public:
A() //类A的构造函数
{
p=new char[10]; //构造函数里使用了new,动态申请内存(该内存空间在堆上)
}
……
private:
char *p;
……
}

这时,无论你使用了A a[10];还是A *p=new A;,都有可能产生内存泄露,原因是你在类A的构造函数里使用了new操作符申请了一段空间,但却没有在类A里显示定义析构函数来释放这片空间。

可以对类做如下修改:
class A
{
public:
A() //类A的构造函数
{
p=new char[10]; //构造函数里使用了new,动态申请内存(该内存空间在堆上)
}
~A()
{
delete []p; //析构函数里的delete和构造函数里的new对应,用来释放动态申请的内存
}
……
private:
char *p;
……
}

追问

谢谢,终于搞明白了!!!
我觉得动态内存这么强大,那是不是以后基本上就不用char ch[40],这种方法分配内存了?

温馨提示:内容为网友见解,仅供参考
第1个回答  2012-09-29
纠缠这些句子没有必要,况且这句话说的是错的。
类可以不需要动态分配,但它可以全权管理动态分配的内存,这个时候如果不定义复制构造函数,就会有问题。多个实例共同管理一个动态分配的内存,会在任一个析构时导致其它实例出错。

不需要动态内存分配的话就不需要显示定义析构函数,复制构造函数,赋值...
当类的构造函数中动态申请了内存的话,如果new 出该类的一个对象,当你delete对象的时候,只能释放掉该类中的其他成员变量,而动态申请的内存空间就无法释放了,这样就会导致内存泄露。所以在构造函数中动态申请了内存的话,那么就一定要在析构函数中用delete运算符来释放申请的内存。另外,我们知道,如果...

拷贝构造函数vs移动构造函数
2. 函数返回类对象时,系统同样会创建一个临时对象并调用拷贝构造函数。拷贝构造函数有默认情况,即在未明确定义时,编译器会自动生成,通常只进行浅层复制。浅层复制只复制数据成员的值,而不复制指针指向的内存空间。深层复制则会为新对象动态分配内存,并复制指针指向的内存空间,避免指针悬挂问题。防止...

D语言是什么 清楚点 谢谢
这样就不需要复制构造函数、赋值运算符、复杂的析构语义以及同异常处理中的堆栈展开的相互作用。内存资源由垃圾收集程序负责释放,其他资源通过使用 D 的 RAII 特征释放。 三字节码和双字节码。Unicode 是未来。 预处理程序。现代语言不应该需要文本处理,它们应该只需要符号处理。 非虚成员函数。在 C++ 中,由累得设...

C++ Primer Plus学习笔记之类继承
抽象基类包含纯虚函数,不能创建实例,但允许提供虚函数定义。派生类可不使用new创建对象,此时无需定义析构、复制构造和赋值运算符。基类使用new分配内存,派生类必须定义这些方法。继承时要考虑is-a关系,确保可进行显式类型转换和引用。构造函数、析构函数、复制构造函数、赋值运算符、常量使用等方法需谨...

析构函数和构造函数的问题
new和delete是C++标准的运算符 是用来动态分配内存空间的 和malloc和free是同样的功能 不过他们之间并不是可以互相代替的 new和delete可以让对象构造和析构 但是malloc和free就不行了 必须需要显示的手动构造和析构 希望我的回答对你有帮助

为什么通常情况下一个函数不能直接用在赋值运算符
1、既然是操作符重载,就必然会访问类的私有成员变量,根据类的封装性要求,除了友元函数外,其他任何外部操作都是违规的,所以不能用普通函数来重载操作符。2、赋值操作符的重载函数在没有显式定义的情况下,编译程序会自动生成,即使类成员变量包含有指针,也会将指针的值给予复制,所以往往会造成多个...

析构函数和构造函数是不是对成出现的
原因是Peson默认有一个拷贝构造函数,你调用setage2函数传值过去的时候调用了Person默认拷贝构造函数构造了一个对象a,因为a当函数调用完毕以后就会析构.所以实际上是构造三次,析构三次,只是你看不到默认的拷贝构造函数给你打印信息.每个类都有一个析构函数,至少有一个构造函数,即使你不显示的定义构造...

C++语言中,new表示什么的关键字?
此函数接收一个已构造的对象,通过拷贝构造的方式在给定的内存地址p上构造一个新对象,代码中后半截T1(value)便是placement new语法中调用构造函数的写法,如果传入的对象value正是所要求的类型T1,那么这里就相当于调用拷贝构造函数类似的,因使用了placement new,编译器不会自动产生调用析构函数的代码,需要手工的实现:[...

C++构造函数和析构函数详解
析构函数销毁对象的顺序与构建对象的顺序是相反的。因为对象的存储是在栈中的,栈的特性就是先进后出。如果我们使用new运算符来动态的创建一个对象,这个对象是不会自动被销毁的,我们需要手动使用delete销毁,这个时候析构函数随着delete的使用而被调用,在程序结束的时候就不会再销毁这个对象了。

理解\/总结C++中的构造函数和析构函数
它们分别负责对象的初始化和清理工作,这些操作是编译器强制要求的,即使不显式定义,编译器也会提供默认的空实现。构造函数用于在创建对象时为成员属性赋值,无返回值,函数名与类名相同,并支持重载,确保仅在创建对象时调用一次。析构函数则在对象销毁前自动执行清理工作,无返回值,名前加~,且不支持...

相似回答