![](/img/trans.png)
[英]c++ copy constructor vs move constructor for std::vector
[英]C++, how to correctly copy std::vector<Class *> in copy constructor?
我正在使用這兩個課程
// This is generic data structure containing some binary data
class A {
public:
A();
A(const A&);
~A();
}
// Main data container
class B {
public:
B();
B( const B&);
~B();
protected:
std::vector<A *> data;
}
// Copy constructor for class b
B::B( const B& orig):data() {
for( std::vector<A *>::const_iterator it = orig.data.begin();
it < orig.data.end(); ++it){
data.push_back( new A( *(*it)));
}
}
我想這堂課會做到這一點,但我找到了如何達到完美的目標。
首先:data()
- 這是初始化空向量所需的初始化(這是編寫一個好的和干凈的代碼的一部分)?
如何在復制構造vector::iterator
中使用vector::iterator
,我發現的唯一方法就是我寫入代碼的那個(const應該是復制構造函數必需的)。
僅復制矢量會復制指針值而不是整個對象?
最后新的數據初始化...有什么辦法可以用較小的代碼替換整個循環和/或是否有任何標准如何為包含對象指針的std :: containers編寫復制構造函數 ?
子問題:我假設使用vector<A *>
比僅僅為vector<A>
(不是每次都復制,決定是否(不)復制對象的權力......)更加合適和有效。
data()
不是必需的,因為在輸入構造函數之前,它將自動完成到向量。 您只需初始化POD類型的成員或沒有默認構造函數(或引用,常量等)的類型。
您可以使用另一個元素的元素數初始化向量,以便向量在增長時不必調整自身大小。 如果你不這樣做,你將從一個小向量開始,並通過分配和重新分配逐步達到目標大小。 這將使矢量從一開始就具有正確的大小:
B::B(const B& orig) : data(orig.data.size()) {
for (std::size_t i = 0; i < orig.data.size(); ++i)
data[i] = new A(*orig.data[i]);
}
請注意,您不再使用push_back
因為向量已經充滿了orig.data.size()
默認構造的元素數(在指針的情況下為NULL
)。
這也會減少代碼,因為您可以使用整數來迭代它而不是迭代器。
如果你真的想使用迭代器,你可以這樣做
B::B(const B& orig) : data(orig.data.size()) {
// auto is preferable here but I don't know if your compiler supports it
vector<A*>::iterator thisit = data.begin();
vector<A*>::const_iterator thatit = orig.data.cbegin();
for (; thatit != orig.data.cend(); ++thisit, ++thatit)
*thisit = new A(**thatit);
}
這樣做的好處是它可以通過改變迭代器的類型來處理其他容器類型(比如list
)(當然,如果你有auto
話,它會消失)。
如果要添加異常安全性,則需要try/catch
塊:
B::B(const B& orig) : data(orig.data.size()) {
try {
// auto is preferable here but I don't know if your compiler supports it
vector<A*>::iterator thisit = data.begin();
vector<A*>::const_iterator thatit = orig.data.cbegin();
for (; thatit != orig.data.cend(); ++thisit, ++thatit)
*thisit = new A(**thatit);
} catch (...) {
for (vector<A*>::iterator i = data.begin(); i != data.end(); ++i)
if (!*i)
break;
else
delete *i;
throw;
}
}
這樣,如果其中一個new
調用拋出異常,您就不會有內存泄漏。 當然你可以使用try/catch
以及沒有迭代器的方式,如果你寧願這樣做的話。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.