Quando eu faço isso:
std::vector<int> hello;
Tudo funciona muito bem. No entanto, quando eu faço um vetor de referências:
std::vector<int &> hello;
Eu recebo erros horríveis como
erro C2528: 'ponteiro': o ponteiro para referência é ilegal
Quero colocar um monte de referências a estruturas em um vetor, para não precisar me intrometer com ponteiros. Por que o vetor está fazendo uma birra sobre isso? Minha única opção é usar um vetor de ponteiros?
Respostas:
O tipo de componente de contêineres como vetores deve ser atribuível . As referências não são atribuíveis (você só pode inicializá-las uma vez quando são declaradas e não pode fazer com que elas façam referência a outra coisa posteriormente). Outros tipos não atribuíveis também não são permitidos como componentes de contêineres, por exemplo,
vector<const int>
não é permitido.fonte
sim, você pode procurar
std::reference_wrapper
que imita uma referência, mas é atribuível e também pode ser "recolocado"fonte
get()
primeiro ao tentar acessar o método de uma instância de uma classe neste wrapper? Por exemplo,reference_wrapper<MyClass> my_ref(...); my_ref.get().doStuff();
não é muito referência como..get()
. O que os timdiels querem éoperator.
; dê uma olhada nas últimas propostas / discussões sobre isso.Por sua própria natureza, as referências só podem ser definidas no momento em que são criadas; ou seja, as duas linhas a seguir têm efeitos muito diferentes:
Além disso, isso é ilegal:
No entanto, quando você cria um vetor, não há como atribuir valores a seus itens na criação. Você está essencialmente apenas criando um monte do último exemplo.
fonte
Ion Todirel já mencionou uma resposta YES usando
std::reference_wrapper
. Desde o C ++ 11 , temos um mecanismo para recuperar o objetostd::vector
e remover a referência usandostd::remove_reference
. Abaixo é dado um exemplo compilado usandog++
eclang
com a opção-std=c++11
e executado com sucesso.fonte
std::remove_reference<>
aqui. O objetivo destd::remove_reference<>
é permitir que você escreva "o tipo T, mas sem ser uma referência, se for um". O mesmostd::remove_reference<MyClass&>::type
acontece com a escritaMyClass
.for (MyClass obj3 : vec) std::cout << obj3.getval() << "\n";
(oufor (const MyClass& obj3: vec)
se você declarargetval()
const, como deveria).boost::ptr_vector<int>
vai funcionar.Editar: foi uma sugestão a ser usada
std::vector< boost::ref<int> >
, que não funcionará porque você não pode construir por padrão aboost::ref
.fonte
resize
.É uma falha na linguagem C ++. Você não pode usar o endereço de uma referência, pois a tentativa resultaria na referência ao endereço do objeto e, portanto, você nunca poderá obter um ponteiro para uma referência.
std::vector
trabalha com ponteiros para seus elementos, portanto, os valores que estão sendo armazenados precisam poder ser apontados. Você precisará usar ponteiros.fonte
sizeof
referência a.TL; DR
Use
std::reference_wrapper
assim:Demo
Resposta longa
Como o padrão sugere , para um contêiner padrão
X
contendo objetos do tipoT
,T
deve serErasable
deX
.Erasable
significa que a seguinte expressão está bem formada:A
é alocador tipo de recipiente,m
é exemplo alocador ep
é um ponteiro de tipo*T
. Veja aqui paraErasable
definição.Por padrão,
std::allocator<T>
é usado como alocador de vetor. Com o alocador padrão, o requisito é equivalente à validade dep->~T()
(Observe queT
é um tipo de referência ep
é ponteiro para uma referência). No entanto, o ponteiro para uma referência é ilegal , portanto, a expressão não está bem formada.fonte
Como já mencionado, você provavelmente acabará usando um vetor de ponteiros.
No entanto, você pode considerar o uso de um ptr_vector !
fonte
Como os outros comentários sugerem, você está limitado a usar ponteiros. Mas se ajudar, aqui está uma técnica para evitar o enfrentamento direto de ponteiros.
Você pode fazer algo como o seguinte:
fonte
reinterpret_cast
não é necessário