簡體   English   中英

C ++,如何在復制構造函數中正確復制std :: vector <Class *>?

[英]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.

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