Делает станд.:: вектор использует оператор присваивания своего типа значения к 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;
}
11
задан user383352 17 July 2010 в 18:41
поделиться

2 ответа

Стандарт 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 это проще всего в существующем виде.)

13
ответ дан 3 December 2019 в 06:44
поделиться

Проблема в том, что типы в контейнере должны быть назначаемыми.

Поскольку вы не определяете оператор присваивания для своего класса, компилятор сгенерирует его для вас. Оператор присваивания по умолчанию будет выглядеть так:

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

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

5
ответ дан 3 December 2019 в 06:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: