2015-03-31 2 views
7

Следующие не компилируются (очень сложная ошибка, но в принципе «невозможно перегрузить» и «неверное преобразование из« const void * »в« void * »). Я могу понять, почему, например, push_back() не может компилировать, так как вы не можете копировать/перемещать в Foo* const, но почему не это компиляции:вектор константных указателей?

#include <vector> 
using namespace std; 

class Foo; 

int main() 
{ 
    vector<Foo* const> vec; 
} 
+1

Полная ошибка может быть найдена [здесь] (http://ideone.com/EouxNT) –

+0

В C++ 03 векторный элемент должен быть CopyAssignable. В C++ 11 это еще не разрешено, [см. Здесь] (http://stackoverflow.com/questions/6954906/does-c11-allow-vectorconst-t). На самом деле я предлагаю закрыть дубликат этого вопроса, если все согласятся. –

+0

Как вы думаете, вы можете вставить новые элементы в 'vector'? – Jagannath

ответ

10

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

Такая же ошибка, если вы попробуете std::vector<const int>, или на самом деле любой тип const.

+1

Зачем требовать назначения перераспределения? Похоже, что он нуждается в копировании ... –

+0

@KerrekSB: С точки зрения назначения компилятора и способности к копированию сводится к тому же. – datenwolf

+0

Не какой-либо const-квалифицированный тип; он должен работать, когда оператор присваивания является const. – rightfold

1

Вы объявляете вектор, содержащий const указатель Foo, что означает, что указатель не может быть изменен. Когда вы вставляете элемент в вектор, нужно записать в const pointer (недействительно).

Вы уверены, что это не так: std::vector<Foo const *> vec;, где Foo не может быть изменен указателем.

1

Ключевое слово C/C++ const лево-ассоциативное, то есть оно лечит токен слева, за исключением случаев, когда const является первым токеном в инструкции. Таким образом, void *const означает «постоянный (= неизменный) указатель на пустоту».

Следовательно, семантика:

int a; 
void * const ptr = (void*)&a; /* legal */ 

int b; 
ptr = (void*)&b; /* not permitted */ 

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

При написании std::vector<void * const> вы запрашиваете у экземпляра экземпляр шаблона как вектор неизменяемых указателей на пустоту. Однако непреложные средства могут быть назначены только при определении, которое, однако, не летает с динамическим характером std::vector.

3

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

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

Однако, вы можете использовать только std::allocator<T>, когда T является неконстантным объектом, поэтому std::vector<const int> плохо сформирован.

+0

Поскольку C++ 11 векторных элементов не нужно назначать –

+0

@MattMcNabb: Абсолютно верно, отредактирован. –

+0

@MattMcNabb hmmmm, g ++ 4.9.2 и даже gcc5 полагает иначе, но да, вы правы – vsoftco