2010-07-17 88 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