2012-01-24 4 views
6

Je voudrais avoir un vecteur de unique_ptr en tant que membre d'une classe que je fais.Comment déclarer un vecteur de unique_ptr en tant que membre de données de classe?

class Foo { 
    [...] 

private: 
    vector<unique_ptr<Bar>> barList; 
} 

Mais je commence à recevoir des messages d'erreur énigmatiques du compilateur VS2010:

error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 

Avec une poignée de lignes d'erreur ci-dessous ce qui plongent dans la mise en œuvre de Microsoft std::_Copy_impl<> ...

J'ai changé la déclaration de membre en

vector<unique_ptr<Bar>>* barList; 

Et il compile. Mais je ne peux pas m'empêcher de me demander pourquoi je ne peux pas le faire comme je le voulais initialement? Pour des grimaces, j'ai essayé cela et il fonctionne très bien:

vector<Bar> barList; 

Mais maintenant, je perds la commodité de unique_ptr. Je veux mon gâteau et je veux le manger aussi!

+0

Je regardais http://stackoverflow.com/questions/8553464/vector-as-a-class-member et la réponse semble penser que déclarer un 'vecteur' comme je l'ai fait est très bien à faire. Pour une raison quelconque, cependant, il semble déclencher des copies illégales lors de l'ajout de la partie 'unique_ptr'. –

+1

À quoi ressemblent votre constructeur de copie et votre opérateur d'affectation? –

+0

Affectation privée, mais le constructeur de copie était le coupable. J'ai passé de 'unique_ptr' à' shared_ptr' quand j'ai réalisé que j'utilisais la mauvaise sémantique de propriété. –

Répondre

10

Le problème ici est que quelque part, votre code tente d'appeler l'opérateur "copy-assignment" de Foo.

Cela provoque le compilateur pour tenter de générer un opérateur d'affectation de copie qui appelle les opérateurs d'affectation de copie de tous les sous-objets de Foo. Finalement, cela conduit à une tentative de copier un unique_ptr, une opération qui n'est pas possible.

+0

Merci d'avoir signalé cela. Le compilateur me trompait parce que l'erreur faisait référence à la déclaration du membre et ne mentionnait pas le code incriminé qui causait la copie. J'imagine que c'est une carence en VS2010 et j'espère que cela s'améliorera avec les nouvelles versions. Ma classe 'Foo' a un constructeur de copie, et j'essayais de copier le vecteur de la source' Foo'. La propriété partagée semble être la meilleure solution, donc passer à 'shared_ptr' a fait l'affaire. –

+1

Cela ressemble à un bug dans VS2010 Je reçois cette erreur même si mon code n'essaie jamais d'appeler copy-assigment. Désactiver l'opérateur = en déclarant privé (donc = supprimer n'est pas supporté) résout le problème. – tr3w

-2

Vous ne pouvez pas utiliser unique_ptr dans un vecteur car l'implémentation vectorielle repose fortement sur les valeurs assigner l'opérateur, qui est privé dans unique_ptr. Utilisez shared_ptr à partir de boost ou d'une autre implémentation smart ptr à partir de C++ 11.

+6

'unique_ptr' fonctionne très bien dans un' vector'. [Voir.] (Http://ideone.com/riLhp) –

+0

Les conteneurs C++ 11 sont requis pour fonctionner avec des types de déplacement uniquement, tels que 'unique_ptr'. – bames53

+0

Je voulais dire la façon dont il l'a utilisé. Mais encore, merci, je ne savais pas à propos de emplace_back. – aambrozkiewicz

4

unique_ptr n'a pas de sémantique de copie, donc vous ne pouvez pas utiliser de méthodes qui copieraient l'objet contenu. Vous pouvez faire cela avec des références rvalue en utilisant std::move dans les endroit (s) il essaie de faire une copie. Sans voir votre code je ne peux pas dire où cela serait.

S'il compile dans la deuxième forme, vous n'avez pas utilisé le même code ou il y a un bogue de compilateur. Les deux devraient échouer de la même manière. Votre troisième exemple, le stockage par valeur est le moyen le plus simple à moins que vos objets ne soient grands et coûteux à stocker/copier par valeur.

+1

'auto_ptr' est celui qui n'obéit pas à la sémantique de la copie normale,' unique_ptr' n'a tout simplement pas ** ** la sémantique de la copie – Grizzly

+0

Les réponses de Your et Mankarse sont très similaires. Son, cependant, m'a fait réaliser que je devais aller à la chasse aux sorcières pour le code incriminé (votre réponse a abordé cette question plus subtilement). Vous méritez tous les deux la réponse acceptée, cependant. Merci pour l'aide! –

2

Il manque souvent un std::move(iUniquePtr) quelque part (par exemple lorsque vous utilisez push_back).

0

extraits Un de www.cplusplus.com

std::unique_ptr::operator= 

cession unique_ptr L'objet acquiert la propriété du contenu de x, y compris à la fois le pointeur stocké et le Deleter stocké (ainsi que la responsabilité de supprimer l'objet à un moment donné). Tout objet appartenant à l'objet unique_ptr avant l'appel est supprimé (comme si le destructeur de unique_ptr était appelé).

Mais il y a un avertissement aussi:

Cette page décrit une fonctionnalité introduite par la dernière révision de la norme C++ (2011). Les compilateurs plus anciens peuvent ne pas le supporter.

MSVC 2010 définit comme operator= privée (non copiable), mais prend en charge la méthode swap.

Questions connexes