2013-05-07 55 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; 
} 
相關問題