Подтвердить что ты не робот

Вектор объектов const, выдающих ошибку компиляции

В своем коде

я заявил следующее:
vector <const A> mylist; 

Я получаю следующую ошибку компиляции -

new_allocator.h:75: error: `const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const \[with _Tp = const A]' and `_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const A]' cannot be overloaded

Но если declare -

vector <A> mylist;

мой код компилируется.

Не разрешено ли const в этом контексте?

Я копирую свой код здесь для каждой ссылки -

#include <iostream>
#include <vector>

using namespace std;
class A
{
public:
    A () {cout << "default constructor\n";}
    A (int i): m(i) {cout << "non-default constructor\n";}

private:
    int m;
};

int main (void)
{
    vector<const A> mylist;

    mylist.push_back(1);

    return 0;
}
4b9b3361

Ответ 1

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

Изменить: я полагаю, что для действительно педантичного я должен, вероятно, добавить чисто теоретическую возможность. Если вы хотели достаточно плохо, вы могли бы определить тип, который можно было бы присваивать, несмотря на то, что он const, что-то вроде этого:

class ugly { 
    mutable int x;
public:
    ugly const &operator=(ugly const &u) const { 
        x = u.x;
        return *this;
    }
};

По крайней мере, в теории, я считаю, что вы, вероятно, должны иметь возможность хранить элементы этого типа в vector, даже если они const. Быстрый тест на создание вектора этих результатов с помощью VС++, но с ошибкой - gcc (g++ 4.8.1/MinGW). Технически я считаю, что это, вероятно, квалифицируется как ошибка в g++ (или ее библиотеке), но я не могу сказать, что это одна из основных проблем. Скорее наоборот, мне интересно (немного), может ли это быть не намеренно, в попытке спасти программиста от чего-то ужасного и глупого.

Ответ 2

Использование метода push_back является проблемой. emplace_back будет компилироваться. Другой вариант (в зависимости от всей ситуации, которую вы здесь не описываете) заключается в использовании vector<A const&>, если вставленные элементы имеют жизнь вне вектора. Элементы в векторе не должны быть назначаемыми, но когда их нет, некоторые функции-члены и алгоритмы не могут использоваться.

Объяснение:

push_back предполагается сначала по умолчанию построить A в векторе, а затем назначить (используя copy-construct) данную ссылку. Это нарушает вашу квалификацию const, поэтому не компилируется.

emplace_back использует "совершенную переадресацию" для непосредственного вызова фактического конструктора.