2013-05-07 53 views
1

我的问题是:以下关于STL堆栈的代码是否正确?如何在STL堆栈中保存用户定义的类型?

在代码

,配合物是用构造和析构定义的用户定义的类。 放置1后,复杂的构造函数和析构函数分别被调用5次, 和放置2后,由于pop(),复杂的析构函数再次被调用5次。因此在总的析构函数中调用的不仅仅是构造函数。 IMO不应该发生。 我的代码是否正确?如果不正确如何纠正它?假设我仍然使用堆栈,而不是叠加

#include <stack> 
#include "complex.h" 
using namespace std; 
void test_stack(){ 
stack<complex> mystack2;  
cout << "Pushing complex..." << endl; 
for (int i=0; i<5; ++i) { 
    complex c(i,i);  
    mystack2.push(c); 
} 
//place 1 
cout << "Popping out complex..." << endl; 
while (!mystack2.empty()) 
{ 
    cout << " " << mystack2.top(); 
    mystack2.pop(); //void pop(); 
} 
//place 2 
cout << endl; 
} 

回答

1

要回答你原来的问题,有没有你的代码错误。但是,你的理解有点偏离。

正如其他人指出,mystack2.push(c)将调用complex的拷贝构造函数。所以总共有5个调用构造函数,5个调用构造函数,10个调用析构函数。

这带来了几个重要的点。正如你已经注意到了,下面的代码:

for (int i=0; i<5; ++i) { 
    complex c(i,i);  
    mystack2.push(c); 
} 

首先创建一个complex(C),然后一个副本添加到堆栈,当c超出范围原本复杂的被破坏。在C++ 11的额外拷贝是不必要的,你可以做到以下几点:

for (int i=0; i<5; ++i) { 
    mystack2.emplace(i, i); 
} 

这将让栈做对象的构造,省去了拷贝的需要。

另一个我认为导致你的困惑的构造函数被称为10次的点是你说的complex只定义了一个构造函数和一个析构函数。如果您没有定义复制构造函数(并且不将其标记为私有或删除),则编译器会自动创建一个。实际上它比C++ 11还要多一点,我会直接向你提出这个问题 - Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?。但需要注意的重要一点是,在这种情况下,您致电push时肯定会调用编译器生成的拷贝构造函数。

+0

正确。我没有意识到在push(c)中调用拷贝构造函数。注意push的定义:void push(const T&x)。我认为它就像foo(const T&x),其中x是通过引用传递的,所以没有构造新的复合体。但似乎push(const T&x)像复制构造一样工作:complex(const T&x)。 – user389955 2013-05-08 03:13:24

+0

@ user389955:在调用push()时,新的'complex'不是构造的。它被构建在push的内部,因为堆栈保存了你传入的值的拷贝* – nobar 2013-05-08 13:05:58

+0

@nobar:thx我明白了。 – user389955 2013-05-16 21:15:35

1

为了简化它,我就不提了,每个这些发生5次:

  • complex c(i,i); - 构造称为
  • mystack2.push(c); - 调用的构造函数
  • c超出范围 - 析构函数称为
  • mystack2.pop(); - 析构函数称为

注意:要查看发生了什么附加跟踪消息在构造函数和析构函数。不要忘记三条规则。

1

你可能没有考虑到的拷贝构造函数,其将在

mystack2.push(c); 

堪称为价值型类,如complex,一个拷贝构造函数会为你自动建立,如果你不定义拥有。

您可以创建一个拷贝构造函数是这样的:

complex(complex const & other) 
: real(other.real) 
, imag(other.imag) 
{ 
    cout<<"complex::copy_constructor called"<<endl; 
} 
相关问题