2013-09-22 3 views
8

だから、私はいつもC++のポインターとは少しぼやけています。同様に、スタック変数を返しますか?

Object* pointer = new Object(); 

Object notpointer(); 

私はポインタがおそらく二番目に関与していることを知っているが、基本的にそれはないポインタです。 (それが実際に何を呼ばれています?)

さらに、私は右、最初のもののために、あなたはあなたがそれを完了したら、いくつかの点で

delete pointer; 

を呼び出すために持っていることを信じますか?もう1つは心配する必要はありません。私は最初にヒープに割り当てられているが、スタックには2番目が割り当てられていて、メソッドが返ってくると遠ざかります。

しかし、関数から何か(プリミティブではない)を返すときはどうですか?

良い例がShould I return std::strings?で書かれている:右、

std::string linux_settings_provider::get_home_folder() { 
    return std::string(getenv("HOME")); 
} 

私が以前に書いたものでは、文字列をスタック上に割り当てられ、関数が戻るときに解放されなければなりませんか?しかし、誰もそれについて何も言わなかったので、それはうまくいくと思います。どうして?一般的に

return new std::string("pointer"); 

return std::string("not-pointer"); 

の違いは何ですか?

また、両方の作業を仮定すると、2つの賛否両論は何ですか?

+1

2つ目は関数です。 – chris

+0

ここではいくつかのコンセプトを組み合わせています。ポインタはメモリアドレスを保持できる単なる変数です。 'new std :: string'はメモリ割り当てとオブジェクト構築を実行しています。これらの2つのものを一緒に使う必要はありません。現代のC++では、通常これをしません。 – greatwolf

+0

文字列はスタックに割り当てられます。 ** **解放されていません。それは破壊される。しかし、コンパイラーはそれを破壊する前にそれをコピーします。 –

答えて

11

ポインタで戻ったときは、表示される方法で動的に割り当てられたオブジェクトを返す必要があります(スタックオブジェクトへのポインタを返すと、後で逆参照されると未定義の動作になります)。これは、あなたが指摘したように、そのオブジェクトを明示的に削除する必要があるため、メモリリークの可能性があります。

あなたは戻り値を受け取るオブジェクトに戻るスタックオブジェクトから返されたオブジェクトをコピーすることで値によって戻って、一方(すなわち第二のスニペット)結果:

std::string res = get_home_folder(); // std::string gets copied into res 

コンパイラreturn value optimizationにコピーするのを避けるためにこれを最適化できます。

+0

@BenjaminLindleyあなたが正しいです、それは正しく見えません。ありがとう! – dasblinkenlight

+0

ありがとう!だから、あなたはポインタではない変数を何と呼んでいますか? – Erhannis

+0

@Erhannis正しいですが、最初のスニペットの 'res'はポインタではありません。 – dasblinkenlight

1

実際にnotpointerというファンクションがObjectを返していると宣言しているので、Object notpointer();を実際に書きたくないと思います。 Object notpointer;を意味する場合は、問題のエンティティはの値となります。実際には、値はスタックに割り当てられます。オブジェクトのメンバーである場合、オブジェクトに埋め込まれます。

何かを返すとき、返されるエンティティは、実際の戻り値が予想される場所にコピーまたは移動されます。戻り値が構築されると、ローカルオブジェクト、すなわちスタック上のオブジェクトは範囲外になり破棄される。たとえコピーコンストラクタやデストラクタが副作用を持っていても、ローカルオブジェクトがとにかく離れていくことを考えれば、コンパイラはコピーを削除し、オブジェクトを正しい場所にすぐに構築することができます。

あなたの2つの戻り文の違いは

  1. new std::string("pointer")を使用するときは、ヒープ上に割り当てられたオブジェクトを取得し、あなたはオブジェクトへのポインタを返すことです。そのポインタを漏洩することは非常に簡単です、あなたは、例えば、適したオブジェクトにすぐにそれを置くことをしたほうが良いだろう、std::unique_ptr<std::string>

    return std::unique_ptr<std::string>(new std::string("pointer")); 
    

    この方法では、ポインタが漏洩されることはありません。もちろん、返品タイプをstd::string*の代わりにstd::unique_ptr<std::string>に変更することもできます。ヒープ割り当ては一般にかなり高価であることに注意してください。

  2. std::string("value")を使用すると、ローカル変数だけが返されます。コピーが省略され、返される値がすぐに必要な場所に作成される可能性があります。関係するすべてのオブジェクトが自動的に破棄されるため、リソースを見直す必要はありません。明示的なヒープ割り当てはなく、スタックの割り当ては非常に高速です。

もちろん、与えられた例では、std::stringは、実際に両方の場合に内部表現を割り当てる必要があります。ポインタが返された場合、追加の内部割り当てがないことが保証されます。一方、std::stringの値を返し、実際に実際にコピーする必要がある場合は、内部メモリをコピーに割り当てる必要があります。つまり、大量のメモリ割り当てを必要とする大きなオブジェクトを返す場合、値を返すアプローチでは、コピーする必要があるリスクが発生します。しかしながら、現在のC++では、オブジェクトは最悪の場合に移動される。すなわち、C++03と同じようにオブジェクトをコピーすることについての心配はあまりない。

+0

申し訳ございません。 'std :: string text(" notpointer ");は' std :: string'、Object obj();の1パラメータコンストラクタと呼ばれ、 'Object'の0パラメータコンストラクタと呼ばれていたので、 。どうやらない。 – Erhannis

関連する問題