我的问题是:关于STL堆栈的以下代码是否正确?
在代码中,complex是一个用户定义的类,定义了构造函数和析构函数。 在第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;
}
答案 0 :(得分:1)
为了简化它,我不会提到每个都发生了5次:
complex c(i,i);
- 名为mystack2.push(c);
- 名为c
超出范围 - 名为mystack2.pop();
- 名为注意:要查看正在进行的操作,请在构造函数和析构函数中添加跟踪消息。不要忘记三个规则。
答案 1 :(得分:1)
您可能没有考虑将在
调用的复制构造函数mystack2.push(c);
对于像complex
这样的值类型类,如果你没有定义自己的复制构造函数,将自动为你创建。
您可以使用以下内容创建复制构造函数:
complex( complex const & other )
: real(other.real)
, imag(other.imag)
{
cout<<"complex::copy_constructor called"<<endl;
}
答案 2 :(得分: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
的调用肯定是调用编译器生成的复制构造函数。