2012-08-05 71 views
14

のstd :: shared_ptrのコンストラクタは、私が期待通りに動作しない:のstd :: shared_ptrのと初期化子リスト

#include <iostream> 
#include <vector> 

void func(std::vector<std::string> strings) 
{ 
    for (auto const& string : strings) 
    { 
     std::cout << string << '\n'; 
    } 
} 

struct Func 
{ 
    Func(std::vector<std::string> strings) 
    { 
     for (auto& string : strings) 
     { 
      std::cout << string << '\n'; 
     } 
    } 
}; 

int main(int argc, const char * argv[]) 
{ 

    func({"foo", "bar", "baz"}); 
    Func({"foo", "bar", "baz"}); 
    //auto ptr = std::make_shared<Func>({"foo", "bar", "baz"}); // won't compile. 
    //auto ptr = std::make_shared<Func>{"foo", "bar", "baz"}; // nor this. 
    return 0; 
} 

私が何か間違ったことやコンパイラであるだろうか?コンパイラは、次のとおりです。

$打ち鳴らす++ --version アップル打ち鳴らすバージョン4.0(タグ/アップル/打ち鳴らす-421.0.57)(LLVMの3.1svnに基づく)

編集:shared_ptrの代わりにmake_shared。ここで

はエラーです:

make -k 
clang++ -std=c++11 -stdlib=libc++ main.cc -o main 
main.cc:28:18: error: no matching function for call to 'make_shared' 
     auto ptr = std::make_shared<Func>({"foo", "bar", "baz"}); 
       ^~~~~~~~~~~~~~~~~~~~~~ 
/usr/bin/../lib/c++/v1/memory:4621:1: note: candidate function not viable: 
    requires 0 arguments, but 1 was provided 
make_shared(_Args&& ...__args) 
^ 
1 error generated. 

答えて

21

これを試してみてください:

auto ptr = std::make_shared<Func>(std::initializer_list<std::string>{"foo", "bar", "baz"}); 

クランは{"foo", "bar", "baz"}の種類を推定するために喜んではありません。私は現在、それが言語がうまくいくかどうか、あるいはコンパイラのバグを見ているかどうかはわかりません。

+5

最後に私は、完璧な転送は、イニシャライザリストが関係しているときには全く完璧ではないことが知られています。 – Puppy

+2

{"foo"、 "bar"、 "baz"}は式ではないので、タイプはありません(autoと一緒に使用する場合を除いて)。 – Cubbi

3

あなたはこれらの引数から構築された新しいオブジェクトを作成したい場合はmake_sharedを使用する必要がある、shared_ptrで指されます。 shared_ptr<T>Tへのポインタに似ています - ポインタTで構築する必要がありますが、Tではありません。

編集:完全な転送は、イニシャライザーリストが関係しているときには完璧ではありません(これは吸います)。これはコンパイラのバグではありません。右辺値Funcを手動で作成する必要があります。

+0

申し訳ありません、問題はmake_sharedにありました。私はfutzing中にshared_ptrに変更しました。 – dpj

4

shared_ptr<T>のコンストラクタは、引数としてT*型のポインタをとります。これは、動的に割り当てられたリソース(または少なくとも削除者が解放できるもの)を指していると仮定します。一方、make_sharedはあなたのための構造を行い、コンストラクタ引数を直接受け取ります。

だから、この言うのいずれか:

std::shared_ptr<Foo> p(new Foo('a', true, Blue)); 

あるいは、より効率的にはるかに良いとは:

auto p = std::make_shared<Foo>('a', true, Blue); 

後者の形式は、あなたのための配分と建設の世話をする、その過程で作成されますより効率的な実装です。

もちろん、make_shared<Foo>(Foo('a', true, Blue))と言うこともできますが、不要なコピーを作成するだけです(不要になる可能性があります)。さらに重要なことは、不要な冗長性が作成されることです。 [は編集]あなたのベクトルを初期化するため、これが最善の方法であってもよい。

auto p = std::make_shared<Func>(std::vector<std::string>({"a", "b", "c"})); 

共有-PTRのコンストラクタがをしながら、重要な点は、しかし、そのmake_sharedは、あなたのための動的割り当てを行いますではなく、には、所有権がになります。

+0

申し訳ありません。あなたたちはとても速いです!問題はmake_sharedで問題だった。 – dpj

+0

"*しかし、それは単に不必要なコピーを作成する*"不必要な動き。 – ildjarn

+0

@ildjarn:まあ、それはすべて依存していますか?とにかく、 "移動"は単なる最適化されたコピーです:-) –

関連する問題