C++ 中的析构函数

渡码 2012-12-15 09:32:21
#include <iostream> 
#include <string>
using namespace std;

class A{
public:
A(int a)
:x(a)
{}
~A()
{
cout<<"A destroy construction.\n"<<endl;
}
private:
int x;
};

class B{
public:
B(int a,int b)
:Aa(a),y(b)
{}
~B()
{}
private:
A Aa;
int y;
};
int main()
{
B b(2,3);
return 0;
}


我的问题是这样的,既然我们定义析构函数后,系统自己定义的仍然存在那么会不会存在调用的二义性?
对于这段代码总感觉~A()会被调用两次,一次是通过B类中系统定义的析构函数调用,另一个当Aa要被撤销是调用。
...全文
526 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
渡码 2013-01-09
  • 打赏
  • 举报
回复
在没有更好的解释了吗
渡码 2013-01-05
  • 打赏
  • 举报
回复
#include <iostream> 
#include <string>
using namespace std;   

class A{
public:
	A(int a)
		:x(a)
	{}
	~A()
	{
		cout<<"A destroy construction.\n"<<endl;
	}
private:
	int x;
};

class B{
public:
	B(int a,int b)
		:Aa(a),y(b)
	{}
	~B()
	{ this->Aa.~A(); }//调用A的析构函数
private:
	A Aa;
	int y;
};
int main() 
{         
	B b(2,3);
	return 0; 
}
这段代码或许会说明问题吧, 自定义的~B()中调用了一次A的析构函数,B类合成的析构函数又调用了一次,与输出的结果相一致。 我觉的这样的问题必须弄明白,否则程序大了的话,一个小的错误或许就会让你检查半天
bigwangdi 2012-12-30
  • 打赏
  • 举报
回复
在不影响对程序运行机理的理解的基础上,对这个可以不那么较真,真心觉得。。
Lena-Yang 2012-12-29
  • 打赏
  • 举报
回复
长见识了
bqw2008 2012-12-29
  • 打赏
  • 举报
回复
析构函数掉2次会异常
FrankHB1989 2012-12-28
  • 打赏
  • 举报
回复
ISO C++11 12.4 5 A defaulted destructor for a class X is defined as deleted if: — X is a union-like class that has a variant member with a non-trivial destructor, — any of the non-static data members has class type M (or array thereof) and M has a deleted destructor or a destructor that is inaccessible from the defaulted destructor, — any direct or virtual base class has a deleted destructor or a destructor that is inaccessible from the defaulted destructor, — or, for a virtual destructor, lookup of the non-array deallocation function results in an ambiguity or in a function that is deleted or inaccessible from the defaulted destructor. A destructor is trivial if it is not user-provided and if: — the destructor is not virtual, — all of the direct base classes of its class have trivial destructors, and — for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor. Otherwise, the destructor is non-trivial. 6 A destructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to destroy an object of its class type (3.7) or when it is explicitly defaulted after its first declaration. 7 Before the defaulted destructor for a class is implicitly defined, all the non-user-provided destructors for its base classes and its non-static data members shall have been implicitly defined. 8 After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).
渡码 2012-12-28
  • 打赏
  • 举报
回复
引用 18 楼 SKATE11 的回复:
看来楼主看书是下真功夫了的 值得鼓励 知道析构函数用来销毁资源 一个类只有一个析构函数就已经够了 至于这个问题没多少人会去考虑
有同感,只不过是感觉看到一句自己感觉理解起来模糊的一句话,就像把它搞清楚,要不然感觉别扭
ying0620 2012-12-27
  • 打赏
  • 举报
回复
我认为应该是默认【析构代码】仍要运行,只不过不是单独运行一个函数,而是合并到了自定义析构函数中。 就像CLR中,构造方法总是会在编译时加入成员字段的初始化代码, 也就是说, 编译器是把默认的析构代码合并到了自定义的析构函数中。
stereoMatching 2012-12-27
  • 打赏
  • 举报
回复
我个人的理解是,假如你的class有定义一些class type 如string,vector,list之类的东西 那么就算你定义了自己的destructor 编译器还是会为你合成一个destructor 呼叫这些class type的destructor string.~(), vector.~(), list.~() 这里有一个陷阱,就是编译器并非总是会为我们合成destructor 例如

class trivial{
  int a, b, c;
};
trivial是不会有constructor也不会有destructor的 他的开销和c的struct一模一样 如果有错的话希望各位可以指出来,我这是抛砖引玉
SKATE11 2012-12-27
  • 打赏
  • 举报
回复
看来楼主看书是下真功夫了的 值得鼓励 知道析构函数用来销毁资源 一个类只有一个析构函数就已经够了 至于这个问题没多少人会去考虑
渡码 2012-12-27
  • 打赏
  • 举报
回复
引用 13 楼 Binzo 的回复:
什么是析构?就是对象销毁时前一刻要做的那部分销毁工作的函数。 销毁只有一次,析构函数也只会调用一次。要那么多名头为“析构”的函数干什么。 析构函数到底怎么定义的,我不想去查。原文怎么说,我这会儿也不想去翻。 你看看,int i; i销毁时调用了叫“析构”的东西了吗。说不定,哪天真的会呢?
默认析构函数和合成析构函数不一样吗? 我的理解是因为我们没有定义,编译器自动为我们合成一个,那么这一个就是个默认的,都一样吧。
卖萌de猫 2012-12-24
  • 打赏
  • 举报
回复
你所认为的调用了两次析构函数其实就是调用了一次~
Xomic 2012-12-24
  • 打赏
  • 举报
回复
理解构造函数不?构造函数跟析构函数原理差不多,就是顺序反过来而已!构造的时候会构造两个A吗。。。
小布 2012-12-24
  • 打赏
  • 举报
回复
没定义调用默认的 定义了调用你的。不存在二义性
Binzo 2012-12-23
  • 打赏
  • 举报
回复
什么是析构?就是对象销毁时前一刻要做的那部分销毁工作的函数。 销毁只有一次,析构函数也只会调用一次。要那么多名头为“析构”的函数干什么。 析构函数到底怎么定义的,我不想去查。原文怎么说,我这会儿也不想去翻。 你看看,int i; i销毁时调用了叫“析构”的东西了吗。说不定,哪天真的会呢?
bigwangdi 2012-12-23
  • 打赏
  • 举报
回复
引用 9 楼 Binzo 的回复:
引用 8 楼 Big_Wang5 的回复:在调用你定义的析构函数后,系统还是会调用默认的析构函数,参考《C++Primer》
原话是:
引用the compiler always synthesizes a destructor for us. The synthesized destructor destroys
each nonstatic member in……




在那句话的后面部分,这部分有写,不知道英文原版的是怎么描述的?中文的可能会掺杂翻译人员的理解吧
heis07w 2012-12-23
  • 打赏
  • 举报
回复
引用
一次是通过B类中系统定义的析构函数调用,另一个当Aa要被撤销是调用。
你说的两次就是一次。 B析构一次,析构B时会析构A,就调一次~A。
weikaty 2012-12-23
  • 打赏
  • 举报
回复
编译器会为我们创建一个合成析构函数,用来顺序销毁成员变量,所以系统的这个会执行。二重性代表有歧义 ,系统的析构和我们自己的析构调用时存在一定的顺序,所以不会有二重性,他们不会在同时执行,产生分歧
Binzo 2012-12-23
  • 打赏
  • 举报
回复
引用 8 楼 Big_Wang5 的回复:
在调用你定义的析构函数后,系统还是会调用默认的析构函数,参考《C++Primer》
原话是:
引用
the compiler always synthesizes a destructor for us. The synthesized destructor destroys each nonstatic member in the reverse order from that in which the object was created.
估计作者这么说,只是为了好表达。作者是有权衡的,他并没有说“那个附加的destroys each nonstatic member”就是“析构函数”,或是“之后又调用了xx析构函数”。他只是说“合成了一个析构函数。”,不能说默认的析构函数还在。 至于算不算“某种析构”,将来这个概念在文字上怎么讲,看这种说法能不能流行了。
bigwangdi 2012-12-23
  • 打赏
  • 举报
回复
引用 6 楼 Binzo 的回复:
引用 2 楼 RJGCSS 的回复:不是吧,系统定义的析构函数仍然还在才对吧。不是吧。
在调用你定义的析构函数后,系统还是会调用默认的析构函数,参考《C++Primer》
加载更多回复(7)

65,210

社区成员

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

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