2012-03-08 15 views
40

próbuję zainicjować takie std::vector<std::unique_ptr<std::string>> w sposób, który jest równoważny do przykładu z Bjarne Stroustrup's C++11 FAQ:Inicjowanie pojemnik unique_ptrs z listy inicjatora nie z GCC 4.7

using namespace std; 
vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails 
unique_ptr<string> ps { new string{"42"} }; // OK 

widzę żadnego powodu, dlaczego ta składnia powinna zawieść . Czy jest coś nie tak z tym sposobem inicjowania kontenera?
Komunikat o błędzie kompilatora jest ogromny; Odpowiedni segment znajduje się poniżej:

/usr/lib/gcc-snapshot/lib/gcc/i686-linux-gnu/4.7.0/../../../../include/c++/4.7.0 /bits/stl_construct.h:77:7: error: no matching function for call to 'std::unique_ptr<std::basic_string<char> >::unique_ptr(std::basic_string<char>&)'

Jaki jest sposób naprawienia tego błędu?

+3

Podejmuje wejściowy iterator ctor – PlasmaHH

+0

Bardzo podobny do http://stackoverflow.com/a/9504162/841108 –

+0

@PlasmaHH W moim rzeczywistym kodzie miałem wiele wpisów na liście inicjalizacyjnej, więc nie wierzę to jest problem. – juanchopanza

Odpowiedz

47

unique_ptr to explicit. Więc nie można utworzyć bez pośrednictwa z new string{"foo"}. Musi to być coś w rodzaju unique_ptr<string>{ new string{"foo"} }.

Co prowadzi nas do tego

vector<unique_ptr<string>> vs { 
    unique_ptr<string>{ new string{"Doug"} }, 
    unique_ptr<string>{ new string{"Adams"} } 
}; 

Jednak może to wyciek, jeśli jeden z konstruktorów nie powiedzie się. Jest to bezpieczniejsze w użyciu make_unique:

vector<unique_ptr<string>> vs { 
    make_unique<string>("Doug"), 
    make_unique<string>("Adams") 
}; 

Ale ... initializer_list s zawsze wykonywać kopie i unique_ptr s nie są copyable. Jest to bardzo denerwujące w przypadku list inicjalizujących. Możesz hack around it, lub awarię do inicjalizacji z połączeniami do emplace_back.

Jeśli faktycznie zarządzający string sz inteligentne wskaźniki i to nie tylko dla przykładu, można zrobić jeszcze lepiej: po prostu zrobić vector<string>. Model std::string obsługuje już używane zasoby.

+0

@Xeo, w rzeczywistości, http://stackoverflow.com/questions/6804216/how-to-initialize-a-container-of-noncopyable-with-initializer-list – juanchopanza

+0

+1 za linki! I nie, jestem w rzeczywistości nie martwi się o to, aby utworzyć ciąg znaków unique_ptrs na łańcuch znaków.Jest to tylko przykład z FAQ: – juanchopanza

+5

Pierwszy przykład nie wyciek .. ',' na liście inicjalizacyjnej jest punktem sekwencji (w nowej, nieco bardziej kłopotliwej terminologii , w '{a, b}', 'a' jest zsekwencjonowane przed' b') Patrz C++ 11 §8.5.4/4. Warto jeszcze użyć 'make_unique', –

2

Po "fixing" swoim przykładzie:

#include <vector> 
#include <memory> 
#include <string> 

int main() 
{ 
    std::vector<std::unique_ptr<std::string>> vs = { { new std::string{"Doug"} }, { new std::string{"Adams"} } }; // fails 
    std::unique_ptr<std::string> ps { new std::string{"42"} }; // OK 
} 

Mam bardzo jasny komunikat o błędzie:

error: converting to 'std::unique_ptr<std::basic_string<char> >' from initializer list would use explicit constructor 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = std::basic_string<char>, _Dp = std::default_delete<std::basic_string<char> >, std::unique_ptr<_Tp, _Dp>::pointer = std::basic_string<char>*]' 

Ten błąd mówi, że nie jest możliwe, aby korzystać z unique_ptr „s wyraźny contructor. Konstrukcja

+6

Aaaand ... ten komunikat błędu nic nam nie mówi. * Dlaczego * nie można użyć jawnego ctor? – Xeo

+0

@Xeo - który kawałek tej pracy * jawnie * wywołuje ctor? Może tam być niejawne wołanie, ale to jest zabronione. – Flexo

+3

Semantyka pliku unique_ptr polega na tym, że nie można go skopiować, to jest powód usunięcia konstruktora. Ale czy 'std :: vector' nie powinien się poruszać i być w stanie poruszać się z tymczasowego do wektora? – hirschhornsalz

Powiązane problemy