2010-07-17 33 views
11

如果是這樣,爲什麼?爲什麼不使用值類型的複製構造函數?std :: vector是否將其值類型的賦值運算符用於push_back元素?

我得到以下錯誤:

/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc: In member functio 
n `ClassWithoutAss& ClassWithoutAss::operator=(const ClassWithoutAss&)': 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc:238: instantiate 
d from `void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterato 
r<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = 
ClassWithoutAss, _Alloc = std::allocator<ClassWithoutAss>]' 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:564: instantia 
ted from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = Class 
WithoutAss, _Alloc = std::allocator<ClassWithoutAss>]' 
main.cpp:13: instantiated from here 
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/vector.tcc:238: error: non-st 
atic const member `const int ClassWithoutAss::mem', can't use default assignment 
operator 

運行g。在下面的代碼++ main.cpp中:

/* 
* ClassWithoutAss.h 
* 
*/ 

#ifndef CLASSWITHOUTASS_H_ 
#define CLASSWITHOUTASS_H_ 

class ClassWithoutAss 
{ 

public: 
    const int mem; 
    ClassWithoutAss(int mem):mem(mem){} 
    ClassWithoutAss(const ClassWithoutAss& tobeCopied):mem(tobeCopied.mem){} 
    ~ClassWithoutAss(){} 

}; 

#endif /* CLASSWITHOUTASS_H_ */ 

/* 
* main.cpp 
* 
*/ 

#include "ClassWithoutAss.h" 
#include <vector> 

int main() 
{ 
    std::vector<ClassWithoutAss> vec; 
    ClassWithoutAss classWithoutAss(1); 
    (vec.push_back)(classWithoutAss); 

    return 0; 
} 
+13

如果僅用於'ClassWithoutAss',則爲+1。 – GManNickG 2010-07-17 18:28:35

+2

爲什麼你將括號vec.push_back ...它不會引起任何問題,但似乎有點不必要... – Goz 2010-07-17 18:56:51

+1

這是一個「驢」在「驢」? – sbi 2010-07-17 21:22:01

回答

13

的C++標準03元說必須拷貝構造和禁止複製可分配用於標準容器中。所以一個實現可以隨意使用,無論他們想要什麼。

在C++ 0x中,這些要求是基於每個操作進行的。 (通常,元素必須是可移動的,並且可移動的)。

爲了得到你想要的,你應該使用一個像shared_ptr(來自Boost,TR1或C++ 0x)的智能指針,並且完全禁用可複製性:

class ClassWithoutAss 
{ 
public: 
    const int mem; 

    ClassWithoutAss(int mem):mem(mem){} 
    // don't explicitly declare empty destructors 

private: 
    ClassWithoutAss(const ClassWithoutAss&); // not defined 
    ClassWithoutAss& operator=(const ClassWithoutAss&); // not defined 
}; 

typedef shared_ptr<ClassWithoutAss> ptr_type; 

std::vector<ptr_type> vec; 
vec.push_back(ptr_type(new ClassWithoutAss(1))); 

指針可以被複製得很好,智能指針可以確保您不會泄漏。在C++ 0x中,你可以用std::unique_ptr做到最好,利用移動語義。 (你實際上並不需要共享的語義,但在C++ 03,因爲它代表最簡單的方法。)

+0

我相信你,但你能解釋爲什麼指針而不是定義自己的操作嗎?更快的push_backs?所以我不會浪費我的時間定義操作?我將不得不考慮移動/共享語義。謝謝GMAN。我只有你的幫助有這些問題。 ;) – user383352 2010-07-17 18:57:31

+0

@drenami:你是什麼意思?我使用指針是因爲你想讓你的類在容器中,但是你不能直接使用它。上面的一個抽象是指向你的類的指針,而不是類本身。 (和智能指針只是爲了防止泄漏。) – GManNickG 2010-07-17 18:59:46

+0

但我可以如果我定義一個賦值操作符嗎?所以我的問題是兩個設計的優缺點 - 一個沒有賦值/使用指針,一個賦值。兩者都是選項,因爲我可以編寫ClassWithAss。 – user383352 2010-07-17 19:08:00

4

這裏的問題是,類型的容器必須轉讓。

因爲你不定義類的賦值操作符,編譯器將生成一個給你。默認的賦值運算符將如下所示:

ClassWithoutAss& operator=(ClassWithoutAss const& rhs) 
{ 
    mem = copy.mem; 
    return *this; 
} 
// The compiler generated assignemtn operator will copy all members 
// using that members assignment operator. 

在大多數情況下,這可行。但是member mem是一個const,因此是不可分配的。因此,編譯將嘗試生成賦值運算符時失敗。

+1

我更喜歡使用'Ass' – Balk 2012-02-20 21:16:53

相關問題