5

C ++ 11以前は、大きなオブジェクトを操作する関数があれば、この種のプロトタイプを使用して関数を作成するのが本能でした。

void f(A &return_value, A const &parameter_value);

(ここで、return_valueは、関数の出力を受け取る単なる空白のオブジェクトです。Aは、コピーするのに大きくて費用がかかるクラスです。)

C ++ 11では、移動セマンティクスを利用して、デフォルトの推奨事項(私が理解しているように)がより簡単です。

A f(A const &parameter_value);

戻り値を保持するためにオブジェクトを渡すという、古い方法でそれを行う必要はまだありますか?

4

3 に答える 3

7

A他の人は、安い移動コンストラクターを持っていないかもしれないケースをカバーしました。私はあなたがそうすると思いますA。ただし、「out」パラメーターを渡す必要がある状況がもう1つあります。

がまたはAのようなタイプであり、「out」パラメータにすでに再利用可能なリソース(メモリなど)があることがわかっている場合は、可能であればそのリソースを再利用するのが理にかなっています。たとえば、次のことを考慮してください。vectorstringf

void get_info(std::string&);
bool process_info(const std::string&);

void
foo()
{
    std::string info;
    for (bool not_done = true; not_done;)
    {
        info.clear();
        get_info(info);
        not_done = process_info(info);
    }
}

vs:

std::string get_info();
bool process_info(const std::string&);

void
foo()
{
    for (bool not_done = true; not_done;)
    {
        std::string info = get_info();
        not_done = process_info(info);
    }
}

最初のケースではstring、ループの実行時に容量が増加し、その容量はループの各反復で再利用される可能性があります。string2番目のケースでは、反復ごとにnewが割り当てられます(小さな文字列最適化バッファーは無視されます)。

std::stringさて、これはあなたが決して価値によって戻ってはならないということではありません。この問題を認識し、ケースバイケースで工学的判断を適用する必要があるということだけです。

于 2012-06-16T13:19:02.283 に答える
3

オブジェクトが大きくてコピーするのに費用がかかる可能性があり、そのために移動セマンティクスはコピーで改善できません。検討:

struct A {
    std::array<double,100000> m_data;
};

この方法でオブジェクトを設計するのは良い考えではないかもしれませんが、何らかの理由でこのタイプのオブジェクトがあり、データを入力する関数を作成したい場合は、outパラメーターを使用して行うことができます。

于 2012-06-16T05:00:46.020 に答える
3

コンパイラは戻り値の最適化をサポートしていますか?また、関数はfコンパイラがサポートするRVOを使用できるように設計されていますか?

もしそうなら、はい、必ず値で返します。可変パラメーターを渡すことで何も得られず、このようにすることでコードが大幅に明確になります。そうでない場合は、の定義を調査する必要がありAます。

一部のタイプでは、移動はコピーにすぎません。実際に移動する価値のあるものが含まれていない場合A(所有権を譲渡するポインターなど)、移動しても何も得られません。結局のところ、移動は無料ではありません。これは、オリジナルが所有するものがすべてコピーに転送されていることを知っている単なるコピーです。タイプが何も所有していない場合、移動は単なるコピーです。

于 2012-06-16T05:09:40.420 に答える