如何在STL栈中保存用户定义的类型

how to hold user defined type in STL stack?

本文关键字:用户 定义 类型 保存 STL      更新时间:2023-10-16

我的问题是:以下关于STL堆栈的代码是否正确?

在代码中,complex是定义了构造函数和析构函数的用户定义类。在位置1之后,复杂构造函数和析构函数分别被调用5次,在位置2之后,由于pop(),复杂析构函数再次被调用5次。所以总的来说,析构函数比构造函数被调用的次数更多。在我看来,这不应该发生。我的代码正确吗?如果不正确如何纠正?假设我仍然使用stack而不是stack

#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;  
}  

回答您最初的问题,您的代码没有任何问题。但是,你的理解有点偏差。

正如其他人注意到的,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相比,它实际上有更多的内容,我将引导您了解这个问题的详细信息-自动生成默认/复制/移动操作符和复制/移动赋值操作符的条件?但是,需要注意的重要事项是,在本例中,对push的调用肯定是调用编译器生成的复制构造函数。

您可能没有考虑到将在

处调用的复制构造函数
mystack2.push(c);

对于像complex这样的值类型类,如果您不定义自己的复制构造函数,则会自动为您创建复制构造函数。

你可以这样创建一个复制构造函数:

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

为了简化它,我不会提到每一个都发生5次:

  • complex c(i,i); -构造器名为
  • mystack2.push(c); -构造器名为
  • c超出作用域-析构函数称为
  • mystack2.pop(); -析构函数调用

注意:要查看发生了什么,在构造函数和析构函数中添加跟踪消息。别忘了三个原则