2016-04-03 5 views
0

は、次のコードを考えてみましょう:もっと慣れ親しんでポインタを置き換える方法はありますか?

#include <memory> 
#include <stdio.h> 
#include <stdexcept> 

class Foo { 
    public: 
     Foo(int n) { val =n; printf("Hi %d\n", val); }; 
     ~Foo() { printf("Bye %d\n", val); }; 
    private: 
     int val; 
}; 

int main() 
{ 
    std::shared_ptr<Foo> p = nullptr; // I don't know what I want yet 
    p = std::make_shared<Foo>(1); // OK, I've decided 

    // I've changed my mind, it needs to be something else 
    p = nullptr; 
    p = std::make_shared<Foo>(2); 

    return 0; 
} 

その出力は次のようになります。

Hi 1 
Bye 1 
Hi 2 
Bye 2 

それは不自然な例です。フーはかなり面白いです。それは単にその寿命に関する情報を表示します。

コードのロジックは次のとおりです。私はpを宣言しますが、最初に何をすべきかはわかりません。私はそれが何であるかを知っていることを決定します。それは価値1を取るべきです。私の実際のコードでは、この価値は長続きするかもしれません。

私はそれが1であってはならないと決めました。それは2でなければならないと決めました。それ以前にあったものはすべて破壊されなければなりません。

これまでのところ、私の理解では、上記のコードはメモリ管理の点で優れており、例外の下では堅牢です。

というのが多くの慣用的な方法があります:

p = nullptr; 
p = std::make_shared<Foo>(2); 

私は私が前に持っていたことは破壊する必要があることを言いたいので、私はちょうど、最後の行を書き込むことはできませんが。

+1

_ "前に書いたものは破壊する必要があると言いたいので、最後の行を書くことはできません" _二番目の行'nullptr'を代入する以外の以前の値の破壊を引き起こさないでしょうか? –

+1

私は "p = nullptr"をコメントアウトするとき、出力1、Hi 2、Bye 1、Bye 2を得るので、最初の割り当ては長すぎます。 – blippy

+0

これは、** 2 **オブジェクトが 'p'への代入の前に作成されているためです。 ** 2 **を作成する前に** 1 **オブジェクトを本当に破壊する必要がある場合は、** 2 **を作成する前に 'p'を' nullptr'に設定する必要があります。それはあまりにも曖昧な要件なので、このためのイディオムはありません。 – Motti

答えて

2

ポインタに割り当てるだけで、以前の値は必要ないことを通知するだけで十分です。 共有ポインターのため、それを破壊する必要があるかどうかは分かりませんが、他の所有者がいる可能性があります。

私の意見では、割り当ては十分ですが、shared_ptr::reset()を使用することをお勧めします。

+1

のユースケースのように聞こえます。 'reset()'は制御ブロックと 'Foo'のインスタンスを分離するため効率が悪いです。 –

+0

@RichardHodges、[同意しない](https://lanzkron.wordpress.com/2012/04/22/make_shared-almost-a-silver-bullet/)を除き、私は同意します。 – Motti

+0

しかし、現実的になりましょう。メモリの局所性は、我々が少しの余分なメモリをしばらく保持するかどうかということよりも、ほとんど常に重要です。shared_ptrをコピーするかweak_ptrをロックするのは一般的な操作です。ほとんどの場合、pointeeオブジェクト自体にアクセスします。この場合、make_sharedの場合、オブジェクトの先頭(ホットな部分)はすでにあなたを待っているデータキャッシュにあります。 –

1

あなたは(良い!)慣用たいので、のは、慣用的なことしてみましょう:

#include <memory> 
#include <stdexcept> 
#include <iostream> 

class Foo { 
public: 
    Foo(int n) 
    : val(n) 
    { 
     std::cout << "Hi " << val << "\n"; 
    }; 
    ~Foo() { 
     std::cout << "bye " << val << "\n"; 
    }; 
private: 
    int val; 
}; 

int main() 
{ 
    auto p = std::shared_ptr<Foo>(); // I don't know what I want yet 
    p = std::make_shared<Foo>(1); // OK, I've decided 

    // I've changed my mind, it needs to be something else 
    p = std::make_shared<Foo>(2); 

    return 0; 
} 
1

あなたがここに

p = std::make_shared<Foo>(2); 

それがあった場合は、この行は、pで前のオブジェクトを破壊する何も行う必要はありませんこのオブジェクトへの最後の参照それから、新しいshared_ptrにpに新しい値を割り当てます

関連する問題