la création d'un shared_ptr de unique_ptr

Dans un morceau de code que j'ai revu dernièrement, qui a compilé fine avec g++-4.6, j'ai rencontré un étrange essayez de créer un std::shared_ptr de std::unique_ptr:

std::unique_ptr<Foo> foo...
std::make_shared<Foo>(std::move(foo));

Cela semble plutôt étrange pour moi. Cela devrait être std::shared_ptr<Foo>(std::move(foo)); autant que je sache, même si je ne suis pas tout à fait familier avec les se déplace (et je sais de std::move est seulement un casting, rien ne se est déplacé).

De vérifier avec différents compilateurs sur cette SSC(NUC*)E

#include <memory>

int main()
{
   std::unique_ptr<int> foo(new int);
   std::make_shared<int>(std::move(foo));
}

Résultats de la compilation:

  • g++-4.4.7 donne erreur de compilation
  • g++-4.6.4 compile sans erreur
  • g++-4.7.3 donne erreur interne du compilateur
  • g++-4.8.1 donne erreur de compilation
  • clang++-3.2.1 compile sans erreur

La question est donc: le compilateur est correct du point de vue de la norme? La norme besoin de cela pour être une instruction non valide, une instruction valide ou est-ce tout simplement pas défini?

Plus

Nous avons convenu que certains de ces compilateurs, comme clang++ et g++-4.6.4, de permettre la conversion, alors qu'ils ne le sont pas. Cependant, avec g++-4.7.3 (qui produit une erreur interne du compilateur sur std::make_shared<Foo>(std::move(foo));), correctement rejette int bar(std::move(foo));

En raison de cette énorme différence dans le comportement, je pars de la question, comme il est, même si une partie de celui-ci serait responsable de la réduction de int bar(std::move(foo));.


*) NUC: Pas universellement compilable

  • Sauf Foo a un constructeur qui prend un std::unique_ptr<Foo> il ne devrait pas compiler.
  • c'est source de confusion en disant: "compile avec de corriger l'erreur" quand vous voulez dire "ne pas compiler". Et la question du titre est trompeur, vous n'êtes pas créer un shared_ptr à partir d'un unique_ptr, vous êtes en train de créer un int à partir d'un unique_ptr.
  • J'ai modifié la formulation. Cependant je vais laisser le titre tel qu'il est. Pourquoi? Le but du réalisateur était de créer un std::shared_ptr<Foo> de cette façon. Ce n'est pas le point de cette question de créer un int à partir d'un unique_ptr, mais pourquoi les différents compilateurs permettent à cette déclaration ou à échouer lamentablement.
  • juste pour la référence, j'ai vérifié si unique_ptr est implicitement convertible en un pointeur normal (mais il n'est pas)
  • et il ne devrait pas l'être. Ce serait briser le concept de *unique*_ptr
  • Pourquoi ne pas tout simplement utiliser la sortie: std::unique_ptr<int> foo(new int); std::shared_ptr<int> shptr(foo.release());? (Il n'est pas de compilateur bug.)
  • Oui, c'était ma première lecture de la question. Le point est, la ligne std::make_shared<int>(std::move(foo)); ne devrait pas compiler. C'est la vraie question de savoir si la norme le permet. À mon avis, c'est un bug du compilateur.
  • Comme je l'ai dit, ce n'était pas mon code et que l'intention était de faire un pointeur partagé d'être unique. La manière correcte est via le shared_ptr ctor qui prend un unique_ptr. La mauvaise manière, montré ici produit une variété de différents comportements dans les compilateurs, dont certains sont mauvais.
  • Ne pas écrire std::shared_ptr<int> shptr(foo.release());! C'est du code dangereux qui peut causer une fuite de mémoire. Si shared_ptr ne parvient pas à allouer de son bloc de référence et déclenche une exception vous avez maintenant une fuite de mémoire.
  • ce ne sera pas une fuite de mémoire. la référence du rpc, dit que, dans le cas de l'exception bad_alloc delete ptr sera appelé

InformationsquelleAutor stefan | 2013-09-19