2009-11-07 79 views
10

我知道STL容器如vector在添加對象時複製對象。 push_back方法是這樣的:STL容器如何複製對象?

void push_back (const T& x); 

我很驚訝地看到,它需要的項目作爲參考。我寫了一個示例程序來了解它是如何工作的。

struct Foo 
{ 
    Foo() 
    { 
     std::cout << "Inside Foo constructor" << std::endl; 
    } 

    Foo(const Foo& f) 
    { 
     std::cout << "inside copy constructor" << std::endl; 
    } 
}; 

Foo f; 
std::vector<Foo> foos; 
foos.push_back(f); 

這將複製的對象,我可以看到它在調用拷貝構造

我的問題是,當push_back需要項目作爲參考,它是如何調用複製構造?或者我在這裏錯過了什麼?

任何想法..?

回答

12

它可能使用「placement new」在內部陣列中就地構造對象。展示位置new未分配任何內存;它只是放置你指定的對象,並調用構造函數。語法是new (address) Class(constructor_arguments)

複製構造函數T::T(T const &)被調用來就地創建副本。像這樣(簡化):

template<T> 
void vector<T>::push_back(T const &item) { 
    // resize if necessary 
    new (&d_array[d_size++]) T(item); 
} 

注意T必須對此有一個拷貝構造函數的工作。默認情況下(如果你什麼都不做),它會免費獲得一個。如果您明確定義它,那麼vector<T>必須爲public

Here's how GNU's libstdc++ does it,但我懷疑它會非常有啓發性。有一個分配器(vector的第二個模板參數),使它不那麼簡單。

+0

當T有一個無參數構造函數時,這是可以的。但是當它有一個參數化的構造函數時會發生什麼?矢量如何初始化新對象? – 2009-11-07 13:45:52

+0

當T有一個_copy constructor_時,這是可以的。默認情況下,如果你實現它,除非你明確地將其設置爲'private'或'protected'。 – Thomas 2009-11-07 14:00:36

+0

我編輯了我的答案以澄清。 – Thomas 2009-11-07 14:04:26

1

它使用放置new運算符並將其複製到單位內存中;

新的放置位置會在內存中的指定地址處創建一個新元素,在向量情況下,當前的end();

void push_back(const T& val){ 
::new (&*end()) T(val); 
[increase end] 
} 

看看http://spotep.com/dev/devector.h它有非常明確的代碼(與大多數STL實現相反)。

3

C++ SDK始終將const T &作爲函數參數來提高效率。

在你的情況下,如果以T作爲參數,複製動作將被執行兩次,一次用於將它傳遞給功能push_back(f),一個用於內部將其添加到容器。並以const T&作爲參數只需要一個副本!

+7

沒有C++ SDK。 – GManNickG 2010-09-15 03:34:14

+0

好的,我的意思是像C++語言規範,STL等背後的東西... ... - – learner 2010-12-25 20:20:31