[英]Understanding the construction, copy and destruction when inserting objects to a vector
[英]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
在這里,三個對象c
, b
, a
和然后在向量中的三個對象被破壞。
每當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.