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

работает г 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

+1 если только для класса ClassWithoutAss. – GManNickG

+2

Почему вы скопируете vec.push_back ... это не вызовет каких-либо проблем, но кажется ненужным ... – Goz

+1

Разве это «задница», как у «осла»? – sbi

ответ

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, используя преимущества move-semantics. (На самом деле вам не нужна совместная семантика, но на C++ 03 это проще всего).

+0

Я верю вам, но можете ли вы объяснить, почему указатели вместо определения моих собственных операций? Быстрее push_backs? Поэтому я не трачу свое время на определение операций? Мне нужно изучить семантику move/share. Спасибо, GMan. У меня есть только эти проблемы с вашей помощью. ;) – user383352

+0

@drenami: Что ты имеешь в виду? Я использовал указатели, потому что вы хотите иметь свой класс в контейнере, но вы не можете сделать это напрямую. Одна абстракция выше - указатель на ваш класс, а не сам класс. (И умные указатели только для предотвращения утечек.) – GManNickG

+0

Но я мог бы, если бы я правильно определил оператор присваивания? Поэтому мой вопрос - это про/минусы двух конструкций - один без назначения/с использованием указателей, одно определяющее назначение. Оба варианта, потому что я могу написать ClassWithAss. – user383352

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. 

В большинстве ситуаций это сработает. Но член mem является константой и, следовательно, невозможен. Поэтому компиляция завершится неудачей, когда попытается сгенерировать оператор присваивания.

+1

Я предпочитаю классы с 'Ass' – Balk