关于合成析构函数的几个小问

selooloo 2010-05-12 09:04:21
“不管类是否定义了自己的析构函数,编译器都自动执行类中非static数据成员的析构函数”
“析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合成析构函数仍然运行”
----这是c++primer 4rd的原话

对合成析构函数很不解,问题如下:

1.合成析构函数有必要吗,因为对内置类型的成员,合成析构函数不需要做什么,对类成员,如string成员,没有合成析构函数,超过作用域也会自动调用string析构函数
比如一个函数
void test()
{
string t;
}
test函数结束后,string不也会自动调用析构函数销毁吗,合成析构函数不显得很鸡肋?

2.合成析构函数是什么样的,不会和自己定义的析构函数构成重载吗?规定析构函数是不能重载的啊,或者说合成析构函数不是函数,只是一个运行机制?

3.是不是定义一个类就会合成析构函数,即使是空类

4.合成析构函数会不会被继承?

麻烦高手解答下
...全文
460 46 打赏 收藏 转发到动态 举报
写回复
用AI写文章
46 条回复
切换为时间正序
请发表友善的回复…
发表回复
梦之领域 2012-12-16
  • 打赏
  • 举报
回复
引用 14 楼 mstlq 的回复:
用一则故事帮助楼主理解 “一次大水淹没了整个城市,消防队员开个小船去救一个传教士,传教士对消防队员说,不用你救,上帝会来救我的,过一会儿又来了一艘冲锋舟,传教士又说了相同的话,最来来了一架直升机,传教士还是说上帝会来救我的,最后被淹死了。当他见到上帝的时候问上帝为什么不救他,上帝对他说,我怎么没有救你,我已经派了一小船,一艘冲锋舟,一架直升机来救你了。” “出……
很生动
leo28103 2012-10-26
  • 打赏
  • 举报
回复
楼主概念很混乱,建议再多看几遍C++ primer,多编程试试
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 selooloo 的回复:]
引用 25 楼 pengzhixi 的回复:
嗯 是否一定合成,应该会有评估的,如果所包含的数据成员是有析构函数的话,那么你这个包含的类它就应该合成一个(如果你没提供的话)。像你20楼的class B如果你不提供那么就会合成。

但是c++ primer里讲,即使编写了自己的析构函数,合成的析构函数仍然运行
[/Quote]

嗯 Lippman在 深度探索C++对象模型里面也说过,如果你不提供析构函数编译器也不一定合成析构函数。
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 selooloo 的回复:]
引用 25 楼 pengzhixi 的回复:
嗯 是否一定合成,应该会有评估的,如果所包含的数据成员是有析构函数的话,那么你这个包含的类它就应该合成一个(如果你没提供的话)。像你20楼的class B如果你不提供那么就会合成。

但是c++ primer里讲,即使编写了自己的析构函数,合成的析构函数仍然运行
[/Quote]

嗯 Lippman在 深度探索C++对象模型里面也说过,如果你不提供析构函数编译器也不一定合成析构函数。
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 selooloo 的回复:]
引用 25 楼 pengzhixi 的回复:
嗯 是否一定合成,应该会有评估的,如果所包含的数据成员是有析构函数的话,那么你这个包含的类它就应该合成一个(如果你没提供的话)。像你20楼的class B如果你不提供那么就会合成。

但是c++ primer里讲,即使编写了自己的析构函数,合成的析构函数仍然运行
[/Quote]

嗯 Lippman在 深度探索C++对象模型里面也说过,如果你不提供析构函数编译器也不一定合成析构函数。
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 pengzhixi 的回复:]
嗯 是否一定合成,应该会有评估的,如果所包含的数据成员是有析构函数的话,那么你这个包含的类它就应该合成一个(如果你没提供的话)。像你20楼的class B如果你不提供那么就会合成。
[/Quote]
但是c++ primer里讲,即使编写了自己的析构函数,合成的析构函数仍然运行
mstlq 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 selooloo 的回复:]
毕竟没有合成析构函数的情况是不会出现的
[/Quote]

“没有合成析构函数”的情况也是存在的……
当一个类的所有非static数据变量都没有析构函数的时候,就没有合成的析构函数……
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 selooloo 的回复:]

合成析构函数会不会被继承?不会。
难道说合成析构函数不是类的成员吗
[/Quote]

你有看过构造函数继承的吗?你有看过拷贝构造函数继承的吗?析构函数也是一个特殊的函数。在你派生类中的析构函数不管你给的析构函数是怎么样的,编译器都会在你的析构函数中插入代码调用基类的析构函数。
你可以将你基类的析构函数声明为private 试试。
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 mstlq 的回复:]
回20楼
您的代码里注释道
test_B();//函数结束后b的内存被收回,a是b的成员,b的内存被收回,意味着b.a的内存也被收回,调用析构函数;当然调用析构函数是有合成析构函数来完成的,但没有合成析构函数的话,b.a的内存被回收后,它不会调用析构函数吗?

有关于绿色那句,这个真不会!!
如果没有合成析构函数,那么就不会输出"destruct A"……

请类比13楼的故事……
……
[/Quote]
你这么肯定? 毕竟没有合成析构函数的情况是不会出现的
对test_A函数就是上帝来拯救a了吧,对test_B函数里b.a难道上帝就对它坐视不理,那不是太不公平了?
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
嗯 是否一定合成,应该会有评估的,如果所包含的数据成员是有析构函数的话,那么你这个包含的类它就应该合成一个(如果你没提供的话)。像你20楼的class B如果你不提供那么就会合成。
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 pengzhixi 的回复:]
我是这么理解的:
1.对含有析构函数的数据成员的析构如果没有提供析构函数的话就会合成一个。但是我觉得编译器在我们提供的情况下应该不会合成了,编译器完全有能力在我们给出的析构函数里面插入一些代码来完成成员的析构。

2.这点就不评论了。

3.不一定要合成。

4.合成析构函数会不会被继承?不会。
[/Quote]
合成析构函数会不会被继承?不会。
难道说合成析构函数不是类的成员吗
mstlq 2010-05-12
  • 打赏
  • 举报
回复
回20楼
您的代码里注释道
test_B();//函数结束后b的内存被收回,a是b的成员,b的内存被收回,意味着b.a的内存也被收回,调用析构函数;当然调用析构函数是有合成析构函数来完成的,但没有合成析构函数的话,b.a的内存被回收后,它不会调用析构函数吗?

有关于绿色那句,这个真不会!!
如果没有合成析构函数,那么就不会输出"destruct A"……

请类比13楼的故事……

请参阅《Inside the C++ Object Model 》
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
LZ为什么就一定会有合成的析构函数呢?
ithiker 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 selooloo 的回复:]
引用 5 楼 gigglesun 的回复:
1.这个可以和“浅复制”与“深复制”的情形类比下。
2.和默认构造函数一样吧,只不过它在自定义的析构函数运行完之后还要再运行,目的就是销毁类中其他类,比如有string等的空间;合成析构函数有点自动垃圾处理的感觉。由于对象不能显示调用析构函数,应该不会构成重载。
3.一个空的类在经过c++预处理之后,编译器会自动为你声明一个复制构造或拷贝构造函数(……
[/Quote]
可以调用,但会出错,所以是不允许的。如果在程序中间也调用了的话,在函数结束处,析构函数还会自动被调用,而两次调用同一个对象的析构函数会出错。
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 mstlq 的回复:]
楼主认为这个“类似”,具体“类似”在哪里呢?
恕我愚钝,一点都察觉不到……
[/Quote]

比如这个程序


#include <iostream>
using namespace std;

class A
{
public:
A(){cout<<"construct A"<<endl;}
~A(){cout<<"destruct A"<<endl;}
};
class B
{
public:
A a;
B(){cout<<"construct B"<<endl;}
~B(){cout<<"destruct B"<<endl;}
};
void test_A()
{
A a;
}
void test_B()
{
B b;
}
int main(void)
{
test_A();//函数结束后a的内存被收回,然后调用析构函数
test_B();//函数结束后b的内存被收回,a是b的成员,b的内存被收回,意味着b.a的内存也被收回,调用析构函数;当然调用析构函数是有合成析构函数来完成的,但没有合成析构函数的话,b.a的内存被回收后,它不会调用析构函数吗
system("pause");
return 0;
}
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 mstlq 的回复:]
楼主认为这个“类似”,具体“类似”在哪里呢?
恕我愚钝,一点都察觉不到……
[/Quote]

比如这个程序


#include <iostream>
using namespace std;

class A
{
public:
A(){cout<<"construct A"<<endl;}
~A(){cout<<"destruct A"<<endl;}
};
class B
{
public:
A a;
B(){cout<<"construct B"<<endl;}
~B(){cout<<"destruct B"<<endl;}
};
void test_A()
{
A a;
}
void test_B()
{
B b;
}
int main(void)
{
test_A();//函数结束后a的内存被收回,然后调用析构函数
test_B();//函数结束后b的内存被收回,a是b的成员,b的内存被收回,意味着b.a的内存也被收回,调用析构函数;当然调用析构函数是有合成析构函数来完成的,但没有合成析构函数的话,b.a的内存被回收后,它不会调用析构函数吗
system("pause");
return 0;
}
selooloo 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 mstlq 的回复:]
楼主认为这个“类似”,具体“类似”在哪里呢?
恕我愚钝,一点都察觉不到……
[/Quote]

比如这个程序


#include <iostream>
using namespace std;

class A
{
public:
A(){cout<<"construct A"<<endl;}
~A(){cout<<"destruct A"<<endl;}
};
class B
{
public:
A a;
B(){cout<<"construct B"<<endl;}
~B(){cout<<"destruct B"<<endl;}
};
void test_A()
{
A a;
}
void test_B()
{
B b;
}
int main(void)
{
test_A();//函数结束后a的内存被收回,然后调用析构函数
test_B();//函数结束后b的内存被收回,a是b的成员,b的内存被收回,意味着b.a的内存也被收回,调用析构函数;当然调用析构函数是有合成析构函数来完成的,但没有合成析构函数的话,b.a的内存被回收后,它不会调用析构函数吗
system("pause");
return 0;
}
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
我是这么理解的:
1.对含有析构函数的数据成员的析构如果没有提供析构函数的话就会合成一个。但是我觉得编译器在我们提供的情况下应该不会合成了,编译器完全有能力在我们给出的析构函数里面插入一些代码来完成成员的析构。

2.这点就不评论了。

3.不一定要合成。

4.合成析构函数会不会被继承?不会。
pengzhixi 2010-05-12
  • 打赏
  • 举报
回复
我是这么理解的:
1.对含有析构函数的数据成员的析构如果没有提供析构函数的话就会合成一个。但是我觉得编译器在我们提供的情况下应该不会合成了,编译器完全有能力在我们给出的析构函数里面插入一些代码来完成成员的析构。

2.这点就不评论了。

3.不一定要合成。

4.合成析构函数会不会被继承?不会。
wINDowsKiller 2010-05-12
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 mstlq 的回复:]

C/C++ code
struct mt
{
string t1;
string t2;
~mt(){cout<<"haha";}
};

int main
{
mt t;
return 0;
}//t出了作用域,t的析构函数被调用,同时t1的析构函数和t2的析构函数也会被调用
//为什么t1的析构函数和t2的析构函数也会被调用呢?因为mt的合成构造函……
[/Quote]
这位兄台可能没有理解楼主意思。
如果仅仅运用在栈变量上来讲,C++上语义上析构其实很鸡肋,从这点上来讲,楼主你是对的。
不过堆就没法了。
另外,你应该知道,JAVA里的类实例完全是跑在堆上了。。。
加载更多回复(25)

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧