构造函数/析构函数计数不匹配[重复]

Posted

技术标签:

【中文标题】构造函数/析构函数计数不匹配[重复]【英文标题】:mismatch in constructors/destructors count [duplicate] 【发布时间】:2011-09-30 08:28:44 【问题描述】:

可能重复:C++ basic constructors/vectors problem (1 constructor, 2 destructors)

我有代码:

#include <iostream>
class A   
    
public:    
    A()  std::cout<<"A::A"<<std::endl;     
    ~A()  std::cout<<"A::~A"<<std::endl; 
;

class B : public A

public:
    B() std::cout<<"B::B"<<std::endl; 
    ~B() std::cout<<"B::B"<<std::endl; 
;

void Func( A a )

int main()

    B b;
    Func(b);

在 VS2010EE 中输出将是:

A::A
B::B
A::~A //why twice? Once on gcc!
A::~A
B::~B
A::~A

但是,当我们有复制构造函数时,输出是:

A::A
B::B
A::A(copy)
A::~A
B::~B
A::~A

【问题讨论】:

你总是有一个副本 cosnstructor。如果你自己没有声明一个,而是隐式使用它,编译器会为你定义一个,而提供的编译器不会记录到std::cout ~B 应该打印"B::~B",而不是"B::B" 如果你在 A 析构函数中设置了一个断点,你应该看到它是从哪里被调用的。 @CharlesBailey:谢谢,这经常弹出,但我找不到重复的:/ @CharlesBailey :不确定是不是骗子:为什么 A 析构函数被调用 3 次?我可以理解两个(一个用于临时 A 参数,一个用于原始对象......) 【参考方案1】:

这有点不幸。 VS 应该避免第二个副本;所有优化都在吗?据推测,它在bA 部分调用复制构造函数来创建参数(即对其进行切片),然后将该对象再次复制到堆栈中以进行函数调用。 (在第一个示例中,A 的构造函数没有被调用,因为生成的复制构造函数不打印输出。)当您提供复制构造函数时,它必须直接在堆栈上创建副本。

【讨论】:

那个副本现在不能省略了,可以吗? 我已经尝试了几个优化设置 - 没有变化! '然后将该对象复制到堆栈上':那么它会将第一个复制构造的对象放在哪里? (好点 Roddy;我的意思是函数框架而不是作用域的堆栈框架。)@Martino:如果 gcc 正在执行它,则两个副本之一可以,除非它正在执行不符合标准的操作。您可能希望生成一个直接复制到堆栈的构造函数;可能 VS 正确语义的想法有一些理由不允许这样做,但我不能立即想到它可能是什么。 我不认为有任何利润,但也没有任何东西会禁止它。在任何一种情况下,复制一份或两份都是完全合法的。我怀疑 MSVC 会特例处理琐碎的复制构造函数,并以某种方式错过了合并这两个操作的可能性。【参考方案2】:

你没有计算所有的构造函数。在第一种情况下,调用Func时会调用复制构造函数来创建对象的副本(因为该函数通过值获取其参数)。

当您自己不定义复制构造函数时,编译器会为您生成一个。并且编译器生成的复制构造函数不会打印任何内容,因此它不会出现在您的输出中。

【讨论】:

问题是为什么在使用编译器生成的 copy-ctor 时会出现第二个副本。一份就够了。 因为您创建了两个副本。首先,您在main 中创建一个实例,然后将该实例传递给Func,因为它按值获取参数,所以创建了它的副本。该副本可以被编译器优化掉,但是当您天真地阅读代码时,您会告诉它创建类的实例,然后创建该实例的副本。 “因为你创建了两个副本。首先你在 main 中创建了一个实例”——输出的最后几行对应于 main 中的对象。【参考方案3】:

如果我理解正确,您实际上是在问这个:

VS2010为什么在我没有副本的时候创建一个additional临时 构造函数?

我唯一的答案是“因为它被允许”。似乎在您使用 gcc 时它会被优化掉,并且在您提供用户定义的复制构造函数时也会被优化掉。

这种行为有点奇怪,但完全符合要求。如果所有 C++ 编译器的性能相同,我们只需要一个编译器...

【讨论】:

以上是关于构造函数/析构函数计数不匹配[重复]的主要内容,如果未能解决你的问题,请参考以下文章

构造函数和析构函数中的虚函数调用[重复]

c ++的构造函数和析构函数汇编[重复]

没有虚拟构造函数,只有虚拟析构函数

构造函数和析构函数

构造函数拷贝构造函数析构函数

构造函数 析构函数 拷贝构造函数 ~~~~~~~~~~构造函数