2017-01-02 94 views
-1

在下列情況下,我的對象超出範圍,我訪問了無效的指針:如何防止臨時超出範圍?

struct Animal 
{ 
    char* buffer; 
    Animal() { buffer = new char[100]; } 
    ~Animal() { delete[]buffer; } 
}; 


int main() 
{ 
    vector<Animal> list; 

    { 
     Animal dog; 
     list.push_back(dog); 
    } 

    list[0].buffer[50] = 7; // Buffer's been deleted, can't access it 
} 

我想,以防止這將是構建動物對象在向量地方的最佳方式,但我不不知道該怎麼做。我想過做:

list.push_back(Dog()); 

但是,這仍然會創建一個臨時的,除非它優化掉,因爲在另一個地方(另一個編譯器)我寧願不依賴於它可能不會做同樣的事情。

編輯:感謝雷米勒博我已經學會了,你可以直接在載體,沒有臨時工,沒有拷貝構造一個矢量元素,用函數:

template< class... Args > 
void emplace_back(Args&&... args); 

我不知道怎麼一個可變模板參數有效,但描述如下:

將新元素追加到容器的末尾。通過std :: allocator_traits :: construct構造的元素是 ,通常 使用placement-new在容器提供的位置 處就地構造元素。參數args ...作爲std :: forward(args)被轉發到 的構造函數中......

+0

我不明白這個問題。你是不是要求你把不是默認構造的東西放到'std :: vector'中? –

+0

這不是'reserve()'的作用。 –

+1

「之後我使用我的vectorOfAnimals [0]並訪問一個無效指針」你對「無效指針」的含義是什麼?它在哪裏? – songyuanyao

回答

3

問題不在臨時超出範圍。真正的問題是Animal由於沒有實現拷貝構造函數或拷貝賦值操作符而違反了Rule of three

當您將臨時推入向量中時,會創建對象的副本,但編譯器生成的副本構造函數只是按原樣複製指針,但不會分配內存的副本。因此,當臨時被破壞時,內存在析構函數中被釋放,並且副本留下一個指向無效內存的懸掛指針。

添加一個拷貝構造函數分配新內存:

struct Animal 
{ 
    char* buffer; 

    Animal() { 
     buffer = new char[100]; 
    } 

    Animal(const Animal &src) { 
     buffer = new char[100]; 
     std::copy(src.buffer, src.buffer+100, buffer); 
    } 

    ~Animal() { 
     delete[] buffer; 
    } 

    Animal& operator=(const Animal &rhs) { 
     if (this != &rhs) { 
      std::copy(rhs.buffer, rhs.buffer+100, buffer); 
     } 
     return *this; 
    } 
}; 

或者,使用std::vector代替原始指針,讓編譯器生成適合拷貝構造函數,拷貝賦值操作符和析構函數爲您提供:

struct Animal 
{ 
    std::vector<char> buffer; 
    Animal() : buffer(100) {} 
}; 

或者,只需分配存儲器,而不是靜態的動態:

struct Animal 
{ 
    char buffer[100]; 
}; 
+0

謝謝。這是我的錯,因爲不清楚。我想學習如何避免複製。我認爲有辦法在矢量中構建一個對象。 – Zebrafish

+0

@TitoneMaurice在你的問題中什麼也沒有提示你避免複製的目標。在C++ 11之前,你無法避免拷貝。在C++ 11及更高版本中,您可以使用'emplace_back()'而不是'push_back()'。但是,每當一個班級管理不能被淺拷貝的資源時,你仍然應該遵循三規則(以及C++ 11及更高版本中的五規則)。 –

+0

vector :: emplace_back()不起作用。當我做我的Vector.emplace_back(myStruct(arg1,arg2));它首先構造myStruct,然後在向量中構造一個新的構造。 Grrrr,一次一件事。如果emplace_back()不工作,我想我應該問一個關於它的問題。 – Zebrafish