ホームページ >バックエンド開発 >C++ >「push_back」がベクター内で複数のコピー コンストラクター呼び出しをトリガーするのはなぜですか?

「push_back」がベクター内で複数のコピー コンストラクター呼び出しをトリガーするのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-11-01 07:17:02602ブラウズ

Why Does `push_back` Trigger Multiple Copy Constructor Calls in a Vector?

ベクトルの Push_back と複数のコピー コンストラクター呼び出しの謎

ベクトルを扱うとき、push_back 操作で必要となるのは数回のコピー コンストラクターの呼び出しのみであると予想されるかもしれません。ただし、複数の呼び出しなど、特定のケースでは予期しない動作が発生する可能性があります。

次のコード スニペットを考えてみましょう:

<code class="cpp">class Myint {
    int my_int;
public:
    Myint() : my_int(0) { /* ... */ }
    Myint(const Myint& x) : my_int(x.my_int) { /* ... */ }
};

int main() {
    vector<Myint> myints;
    Myint x;

    myints.push_back(x); // Call 1
    x.set(1);
    myints.push_back(x); // Call 2
}</code>

直感的には、コピー コンストラクターの呼び出しが 2 つあると予想されます。1 つは最初の Push_back です。そして2番目にもう1つ。ただし、出力は別の話をします:

Call 1 (default constructor)
Call 2 (copy constructor: my_int = 0)
Call 3 (copy constructor: my_int = 0)
Call 4 (copy constructor: my_int = 1)

なぜ余分な呼び出しが必要ですか?

内部ベクトルのダイナミクス

内部では、ベクトルは通常、一定量のメモリをストレージ。割り当てられたスペースが使い果たされると、ベクターはさらに多くのメモリを再割り当てする必要があります。この再割り当てにより、既存の要素の新しいメモリへのコピーがトリガーされます。

指定されたコードでは、2 番目の Push_back で再割り当てが必要になります。 Myint のコンストラクターは 2 回しか呼び出されないにもかかわらず、コピー コンストラクターは 3 回利用されます。これは、コピー コンストラクターを使用して最初の要素を新しく割り当てられたメモリに移動し、元の値 (my_int = 0) で初期化され、次にコピー コンストラクターが再度呼び出され、更新された値 (my_int = 0) で初期化された 2 番目の要素が作成されるためです。 my_int = 1).

パフォーマンスの最適化

これらの不要なコピーを軽減するには、次のことをお勧めします。

  • メモリの予約: を増やすことにより、ベクターの初期容量を使用すると、再割り当てを防止し、コピー操作を最小限に抑えることができます。
  • Emplace_back を使用する: このメソッドを使用すると、コピーや移動を避けて、要素をその場で直接構築できます。

この場合、reserve を使用してメモリを事前に割り当てると、コピー コンストラクターの呼び出しが効果的に 2 回に減ります。さらに、emplace_back(0) はコピーを完全に削除し、最適なパフォーマンスをもたらします。

以上が「push_back」がベクター内で複数のコピー コンストラクター呼び出しをトリガーするのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。