簡體   English   中英

試驗復制載體的構建

[英]experiment with copy construction for a vector

在嘗試通過“按值傳遞”和隨后的破壞來嘗試復制構造時,我嘗試了以下代碼:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Rock{
int sz;
public:
Rock():sz(0){cout<< "Default ctor"<<endl;}
~Rock(){cout<< "Dtor"<<endl;}
Rock(const Rock& r){ cout << "Copy ctor" << endl; sz = r.sz;}
Rock& operator=(const Rock& r) {cout << "In assignment op" << endl; sz = r.sz;}
};

int main()
{
vector<Rock> rocks;
Rock a, b, c;
rocks.push_back(a);
rocks.push_back(b);
rocks.push_back(c);
return 0;
}

並得到以下輸出。 到第7行為止,一切都很好,但是我不明白從那時起會發生什么。 有人可以澄清嗎?

Default ctor
Default ctor
Default ctor
Copy ctor
Copy ctor
Copy ctor // all fine I got it...
Dtor
Copy ctor
Copy ctor
Copy ctor
Dtor
Dtor
Dtor
Dtor
Dtor
Dtor
Dtor
Dtor

讓我們將輸出關聯到相應的代碼行。

Rock a, b, c;

Default ctor
Default ctor
Default ctor

你可能想通了自己。 :-)

rocks.push_back(a);

Copy ctor

同樣,您可能正確地找到了答案。

rocks.push_back(b);

Copy ctor
Copy ctor // all fine I got it...
Dtor

您的評論顯然是錯誤的,因為您幾乎可以肯定沒有兩個構造函數調用與此語句關聯起來:-)

什么情況是,添加的副本的時候a ,矢量只分配足夠的內存來存儲的一個副本a (它會被允許分配更多,雖然)。 因此,必須分配一個新的內存塊大到足以容納兩個拷貝a b ,復制的拷貝a存儲在舊的內存塊到新的一個,復制b后,再破壞的原始副本a解除分配(現在不再需要)原始存儲塊之前。

rocks.push_back(c);

Copy ctor
Copy ctor
Copy ctor
Dtor
Dtor

通過以上解釋,您現在應該能夠猜測這里發生了什么。

但是請注意,如果您將另一個元素推回向量,則很可能再次得到一個拷貝構造函數,而沒有析構函數調用。 這是因為向量的一種典型策略是在每一步中將分配的內存加倍,因此在推回c它很可能為4個對象分配了空間。 實際上, std::vector是使用指數策略所必需的(盡管不需要使用因數2,並且有人認為黃金均值是一個更好的因數)。

}

Dtor
Dtor
Dtor
Dtor
Dtor
Dtor

在這里,三個對象cba和然后在向量中的三個對象被破壞。

每當std::vector必須增加其容量時(因為您要插入更多元素),它都需要分配新存儲,將所有現有元素從舊存儲復制到新存儲,然后刪除舊元素。 因此,您將獲得對復制構造函數和析構函數的“額外”調用。

如果在對push_back每次調用之間放置一個cout語句,則應有助於闡明與每個push_back相關聯的ctor / dtor調用。

但這是我對年代的猜測:

Default ctor
Default ctor
Default ctor

// First push_back() (capacity initially 1)
Copy ctor    // Copy a into vector

// Second push_back() (capacity now grows to 2)
Copy ctor    // Copy rocks[0] to new storage
Copy ctor    // Copy b into vector
Dtor         // Destruct rocks[0] in old storage

// Third push_back() (capacity now grows to 4)
Copy ctor    // Copy rocks[0] to new storage
Copy ctor    // Copy rocks[1] to new storage
Copy ctor    // Copy c into vector
Dtor         // Destruct rocks[0] in old storage
Dtor         // Destruct rocks[1] in old storage

// End of main
Dtor         // Destruct rocks[0]
Dtor         // Destruct rocks[1]
Dtor         // Destruct rocks[2]
Dtor         // Destruct c
Dtor         // Destruct b
Dtor         // Destruct a

修改代碼以輸出更多信息很容易:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Rock{
    int sz;
public:
    Rock():sz(0){cout<< "Default ctor"<<endl;}
    Rock(int x):sz(x){cout<< "int ctor " << x <<endl;}
    ~Rock(){cout<< "Dtor " << sz <<endl;}
    Rock(const Rock& r){ cout << "Copy ctor from " << r.sz << endl; sz = r.sz;}
    Rock& operator=(const Rock& r) {cout << "Copy ctor " << sz << " from " << r.sz << endl; sz = r.sz;}
};

int main()
{
    vector<Rock> rocks;
    Rock a(1), b(2), c(3);
    rocks.push_back(a);
    rocks.push_back(b);
    rocks.push_back(c);
    return 0;
}

它打印(帶有說明):

int ctor 1
int ctor 2
int ctor 3
Copy ctor from 1  // copies a into the vector
                  // push_back(a) returns (capacity == 1)
Copy ctor from 1  // vector reallocates to a greater storage
Copy ctor from 2  // copies b into the vector
Dtor 1            // destroy the old elements
                  // push_back(b) returns (capacity == 2)
Copy ctor from 1  // vector reallocates to a greater storage
Copy ctor from 2  
Copy ctor from 3  // copy c into the vector
Dtor 1            // destroy the old elements
Dtor 2
                  // push_back(c) returns (capacity == 4)
Dtor 3            // destroy the local a, b, c
Dtor 2
Dtor 1
Dtor 1            // destroy the vector and its elements
Dtor 2
Dtor 3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM