Depois de muitas investigações com o valgrind, concluí que std :: vector faz uma cópia de um objeto que você deseja enviar push_back.
Isso é mesmo verdade? Um vetor não pode manter uma referência ou um ponteiro de um objeto sem uma cópia ?!
obrigado
*
ou&
para fazer um ponteiro ou referência.push_back
: leva aconst&
. Ou joga fora o valor (inútil) ou existe um método de recuperação. Então, olhamos para a assinatura deback
, e ela retorna clara&
, de modo que o valor original foi copiado ouconst
foi descartado silenciosamente (muito ruim: comportamento potencialmente indefinido). Assim, assumindo que os projetistasvector
eram racionais (vector<bool>
não obstante), concluímos que ele faz cópias.Respostas:
Sim,
std::vector<T>::push_back()
cria uma cópia do argumento e a armazena no vetor. Se você deseja armazenar ponteiros para objetos em seu vetor, crie um emstd::vector<whatever*>
vez destd::vector<whatever>
.No entanto, você precisa garantir que os objetos referenciados pelos ponteiros permaneçam válidos enquanto o vetor mantém uma referência a eles (ponteiros inteligentes utilizando o idioma RAII resolvem o problema).
fonte
push_back
executará uma movimentação em vez de uma cópia se o argumento for uma referência de rvalue. (Os objectos podem ser convertidas em referências rvalue comstd::move()
.)emplace_back
para evitar qualquer cópia ou movimentação (objeto de construção no local fornecido pelo contêiner).Sim,
std::vector
armazena cópias. Como devevector
saber quais são os tempos de vida esperados dos seus objetos?Se você deseja transferir ou compartilhar a propriedade dos objetos, use ponteiros, possivelmente ponteiros inteligentes como
shared_ptr
(encontrados no Boost ou TR1 ) para facilitar o gerenciamento de recursos.fonte
boost::ptr_vector
?class Foo { typedef boost::shared_ptr<Foo> ptr; };
apenas para escreverFoo::ptr
.shared_ptr
não é exatamente fogo e esqueça. Veja stackoverflow.com/questions/327573 e stackoverflow.com/questions/701456A partir do C ++ 11, todos os contêineres padrão (
std::vector
,std::map
etc) oferecem suporte à semântica de movimentação, o que significa que agora você pode passar rvalues para contêineres padrão e evitar uma cópia:Como alternativa, você pode usar vários ponteiros inteligentes para obter o mesmo efeito:
std::unique_ptr
exemplostd::shared_ptr
exemplofonte
std::make_unique
(irritantemente) está disponível apenas no C ++ 14 e acima. Diga ao seu compilador para definir sua conformidade padrão de acordo, se desejar compilar esses exemplos.auto pFoo =
para evitar repetições; e todos osstd::string
moldes podem ser removidos (não há conversão implícita de literais parastd::string
)make_unique
pode ser facilmente implementado em C ++ 11, por isso é apenas uma ligeira irritação para alguém preso com um C ++ 11 compiladortemplate<typename T, typename... Args> unique_ptr<T> make_unique(Args&&... args) { return unique_ptr<T>{new T{args...}}; }
std::move()
comstd::shared_ptr
, o ponteiro compartilhado original pode ter seu ponteiro alterado desde que a propriedade foi passada para o vetor. Veja aqui: coliru.stacked-crooked.com/a/99d4f04f05e5c7f3O std :: vector sempre faz uma cópia do que estiver sendo armazenado no vetor.
Se você estiver mantendo um vetor de ponteiros, ele fará uma cópia do ponteiro, mas não a instância para a qual o ponteiro está apontando. Se você estiver lidando com objetos grandes, poderá (e provavelmente deve) sempre usar um vetor de ponteiros. Freqüentemente, o uso de um vetor de ponteiros inteligentes de um tipo apropriado é bom para fins de segurança, pois o manuseio da vida útil do objeto e o gerenciamento de memória podem ser complicados.
fonte
O std :: vector não apenas faz uma cópia do que você está empurrando, mas a definição da coleção afirma que isso será feito e que você não poderá usar objetos sem a semântica correta da cópia em um vetor. Portanto, por exemplo, você não usa auto_ptr em um vetor.
fonte
Relevante no C ++ 11 é a
emplace
família de funções-membro, que permitem transferir a propriedade de objetos, movendo-os para contêineres.O idioma de uso seria semelhante
A movimentação para o objeto lvalue é importante, caso contrário, ela seria encaminhada como uma referência ou referência const e o construtor da movimentação não seria chamado.
fonte
se você não quiser as cópias; então a melhor maneira é usar um vetor de ponteiro (ou outra estrutura que sirva para o mesmo objetivo). se você quiser as cópias; use diretamente push_back (). você não tem outra escolha.
fonte
Por que demorou bastante investigação para descobrir isso! Apenas prove com um código simples, por exemplo
Se "olá mundo" for impresso, o objeto deverá ter sido copiado
fonte