2016-10-16 9 views
5

私は最近Compiler Explorerで遊んでいます。私はポインタパラメータを取るそれらの例の1つをロードし、それを代わりにunique_ptrパラメータを取るように変更しました。しかし、出力アセンブリでは、オペレータ削除の呼び出しが顕著に欠けていたことに気付きました。なぜ誰かが知っているなら、私は不思議です。unique_ptrがコンパイラエクスプローラで削除命令を生成していませんか?

次に、エクスプローラに貼り付けることのできる例を示します。コンパイラのオプションには-O3も入れてください。

#include <memory> 

using std::unique_ptr; 

void maxArray(unique_ptr<double[]> x, unique_ptr<double[]> y) { 
    for (int i = 0; i < 65536; i++) { 
     if (y[i] > x[i]) x[i] = y[i]; 
    } 
} 

編集:代わりに、私はcppreferenceからのコード例の1つに貼り付ける場合も、比較のために、そして私は GET演算子は、出力で、削除を行う

#include <iostream> 
#include <memory> 

struct Foo 
{ 
    Foo()  { std::cout << "Foo::Foo\n"; } 
    ~Foo()  { std::cout << "Foo::~Foo\n"; } 
    void bar() { std::cout << "Foo::bar\n"; } 
}; 

void f(const Foo &) 
{ 
    std::cout << "f(const Foo&)\n"; 
} 

int main() 
{ 
    std::unique_ptr<Foo> p1(new Foo); // p1 owns Foo 
    if (p1) p1->bar(); 

    { 
     std::unique_ptr<Foo> p2(std::move(p1)); // now p2 owns Foo 
     f(*p2); 

     p1 = std::move(p2); // ownership returns to p1 
     std::cout << "destroying p2...\n"; 
    } 

    if (p1) p1->bar(); 

    // Foo instance is destroyed when p1 goes out of scope 
} 

EDIT:krzaqに+1。呼び出し元ではなく呼び出し元であり、パラメータを作成して破棄します。

答えて

6

この問題は、つまるところ:fooのパラメータ生きるん

void foo(unique_ptr<int>) 
{ 
} 

foo(make_unique<int>()); 

以下standardeseは、この問題に適切である:

N4140§5.2.2[expr.call]/4

機能は、それが 定義されている場合、パラメータの有効期間が終了します戻る。各パラメータ の初期化と破棄は、呼び出し元関数のコンテキスト内で行われます。言い換えれば

:あなたのmaxArrayxy年代のデストラクタを呼び出すための責任である必要はありません。 gccはこのように実装しています。そのため、codegenにはdelete呼び出しがありません。

+1

"各パラメータの初期化と破棄は、呼び出し関数のコンテキスト内で発生します。"呼び出し元が破壊の責任を負っているわけではありません。 (実際に何を意味するのかは、あなたが引用した段落の残りの部分を読んでください)。 g ++は実際にあなたが引用した最初の文に従っていません。呼び出しを行う完全な式の終わりまでパラメータの破壊を遅らせますが、その文は、関数が戻る前に破壊されなければならないと言います。 C++ 17標準は、このセクションを変更して、その動作を合法にする予定です。 –

+0

@ M.Mこの段落の残りの部分は、仮想関数の例または扱いです。しかし、私はC++で変更された言葉遣いを見ています。 – krzaq

+1

例を参照しています –

関連する問題