如何在STL栈中保存用户定义的类型
how to hold user defined type in STL stack?
我的问题是:以下关于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();
-析构函数调用
注意:要查看发生了什么,在构造函数和析构函数中添加跟踪消息。别忘了三个原则
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- Visual C++(VS2017)中用户定义的转换不明确
- 使用用户定义的参数调用future/async并调用类方法
- 带有用户定义类的c++折叠表达式
- g++用户定义的动态链接库上的全局new和delete运算符
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 修改"std::set"中用户定义类型的值
- 参数包构造函数在类模板中隐藏用户定义的转换
- MAKE:找不到包含的用户定义的头文件?
- C++:用户定义的显式类型转换函数错误
- 从用户定义的类生成格式字符串?
- 为用户定义的类正确调用复制构造函数/赋值运算符
- C++ 向量与用户定义的类比较?(==, <, >)
- STL 用户定义的二进制操作
- 将用户定义的类型与 std::vector 和 std::sort 一起使用
- 为什么用户定义的函数不按照给定的顺序对相同长度的元素进行排序?
- 使用宏编译时使用用户定义的数学函数,或者仅使用 c++ 中标准数学库中的函数
- C++:用户定义的类,以成员字段作为地址