std::vector‹A› ошибка C2582: функция 'operator =' недоступна в

я использую простой вектор push_back для объекта типа A и получаю эту ошибку, это мой код:

class A 
{
    public:
    A(int a,int b,int c);
};


#include "A.h"
....
....
....
....
std::vector<A>* vec_objects = new std::vector<A>();

while(....some condition ...) 
{

    A a(1,2,3)
    vec_objects->push_back(a);
}

получение этой ошибки:

c:\program files\microsoft visual studio 9.0\vc\include\xutility(3159) : error C2582: 'operator =' function is unavailable in 'A'
1>        c:\program files\microsoft visual studio 9.0\vc\include\xutility(3187) : see reference to function template instantiation 'void std::_Fill<A*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1>        with
1>        [
1>            _Ty=A,
1>            _FwdIt=A *
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\vector(1231) : see reference to function template instantiation 'void std::fill<A*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1>        with
1>        [
1>            _Ty=A,
1>            _FwdIt=A *
1>        ]
1>        c:\program files\microsoft visual studio 9.0\vc\include\vector(1153) : while compiling class template member function 'void std::vector<_Ty>::_Insert_n(std::_Vector_const_iterator<_Ty,_Alloc>,unsigned int,const _Ty &)'
1>        with
1>        [
1>            _Ty=A,
1>            _Alloc=std::allocator<A>
1>        ]
1>       

что я сделал не так?


person user63898    schedule 03.07.2012    source источник
comment
Являются ли переменные-члены A константными?   -  person hmjd    schedule 03.07.2012
comment
его компиляция, если я удалю vec_objects-›push_back(a); работает нормально   -  person user63898    schedule 03.07.2012
comment
@user63898: Код, который вы разместили, компилируется, как только я исправлю очевидные синтаксические ошибки: ideone.com/jeMXm . Возможно, вы могли бы опубликовать минимальный полный пример, который воспроизводит ошибку; без этого мы можем только догадываться о проблеме   -  person Mike Seymour    schedule 03.07.2012
comment
Особенно опубликуйте определение класса A (определение = все объявления членов, то есть то, что идет в заголовке; тела методов не нужны), потому что проблема в том, что он не соответствует требованиям push_back, и мы не можем сказать, почему, когда вы этого не делаете. т показать определение.   -  person Jan Hudec    schedule 03.07.2012


Ответы (3)


Вам нужно добавить operator= и copy-constructor в класс A

class A 
{
    public:
    A(int a,int b,int c);
    A(const A& element);
    A& operator=(const A& element);     //which needs definition
};
person Blood    schedule 03.07.2012
comment
Я почти уверен, что оба генерируются неявно. - person Jan Hudec; 03.07.2012
comment
Они не генерируются автоматически, если у вас есть константные свойства (например, вы пытаетесь создать явно неизменяемые типы). - person Brannon; 12.05.2016

Элемент вектора должен быть:

  • Копируемый, т. е. иметь конструктор, совместимый с T(const T&).
  • Назначаемый, т. е. иметь operator=, совместимый с operator=(const T&).
  • Конструируемый по умолчанию, т. е. иметь конструктор, совместимый с T().

Хотя ошибка указывает на то, что назначаемое требование нарушено, код предполагает обратное. Каждый класс получает сгенерированный компилятором конструктор копирования и оператор присваивания, если они не определены вручную, поэтому ваш класс фактически должен быть назначаемым. Однако конструктор по умолчанию создается неявно только в том случае, если другие конструкторы не определены. У вас есть конструктор, поэтому также необходимо определить конструктор по умолчанию.

Как отметил Майк, требования были сокращены до возможности перемещения только в C++11, но вам потребуется компилятор, который уже поддерживает соответствующие функции C++11, и эти функции должны быть включены. Однако пути в ошибках указывают на Visual Studio 9.0, также известную как Visual Studio 2008, которая предшествует C++11, поэтому ограничение применяется.


Копируемые и назначаемые по умолчанию выполняются, если вы их не нарушили. В спецификации сказано,

  • In 12.8.4:

    Если определение класса явно не объявляет конструктор копирования, он объявляется неявно.

  • In 12.8.10:

    Если определение класса явно не объявляет оператор присваивания копирования, он объявляется неявно.

В обоих случаях он определяется только в том случае, если все базовые классы и все члены имеют доступный и недвусмысленный соответствующий конструктор копирования, соответственно, оператор присваивания копирования.

person Jan Hudec    schedule 03.07.2012
comment
Так было до 2011 года. Сейчас требования значительно менее строгие. Для vector тип должен быть перемещаемым и должен быть копируемым или создаваться по умолчанию только для операций, требующих этих свойств. - person Mike Seymour; 03.07.2012
comment
@MikeSeymour: Да, но сообщения об ошибках, указанные в вопросе, явно исходят из Visual Studio 2008, в которой нет следов каких-либо функций C++11 (в то время они все еще находились в состоянии предложения, и Microsoft не проявляла особого интереса на С++) - person Jan Hudec; 03.07.2012
comment
Я уверен, что вам это ясно, но я не эксперт в определении поддерживаемых языковых функций из фрагментов вывода компилятора, и в вашем ответе не упоминается, что он относится к конкретной исторической версии языка. - person Mike Seymour; 03.07.2012
comment
@MikeSeymour: Конечно. Заметка в целом актуальна (компилятор я указал потому, что тоже имею сомнительную честь работать с ним). - person Jan Hudec; 03.07.2012

В коде, который вы разместили, нет ничего плохого. Похоже, ваш реальный класс (или базовый класс) объявляет непубличный оператор присваивания. Это означает, что класс нельзя назначать, поэтому существуют ограничения на его использование в стандартных контейнерах. У вас также будут проблемы, если он не может быть скопирован, то есть если объявлен непубличный конструктор копии.

В С++ 03 его вообще нельзя использовать. Вам нужно будет сделать его копируемым и назначаемым для использования в любом стандартном контейнере.

В С++ 11 его можно хранить в vector, если он подвижен. push_back может не работать, если его нельзя скопировать, и в этом случае вы можете использовать emplace_back(1,2,3) или push_back(std::move(a)).

person Mike Seymour    schedule 03.07.2012