【问题标题】: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 参数,一个用于原始对象......)

标签: c++ visual-studio gcc


【解决方案1】:

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

【讨论】:

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

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

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

【讨论】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2013-09-06
    • 2013-07-07
    • 2022-11-29
    • 2021-03-22
    相关资源
    最近更新 更多