直接初期化とstd :: initializer_listを使用する場合の異なる命令

ローシャン

私はさまざまな初期化方法を試し、さまざまなユースケースとパフォーマンスへの影響に対してそれらが提供する開発者エクスペリエンスを評価していました。その過程で、2つのコードスニペットを作成しました。1つは直接初期化を使用し、もう1つは初期化子リストを使用します。

直接:

class C {
public:
    char* x;

    C() : x(new char[10] {'0','1'}) {}
};

C c;

イニシャライザリスト:

#include <utility>
#include <algorithm>

class C {
public:
    char* x;

    C(std::initializer_list<char> il) {
        x = new char[10];
        std::copy(il.begin(), il.end(), x);
    }
};

C c = {'0','1'};

std::initializer_list同じアセンブリを生成することを期待していました。なぜそれが悪化するのか(より複雑に見える)は理解できますが、実際に悪化した場合は、ここでまったく異なる質問をしていました。より少ない命令でより良いコードを生成するのを見たときの驚きを想像してみてください!

上記のスニペットでgodboltへのリンク- https://godbolt.org/z/i3XZ_K

直接:

_GLOBAL__sub_I_c:
        sub     rsp, 8
        mov     edi, 10
        call    operator new[](unsigned long)
        mov     edx, 12592
        mov     WORD PTR [rax], dx
        mov     QWORD PTR [rax+2], 0
        mov     QWORD PTR c[rip], rax
        add     rsp, 8
        ret
c:
        .zero   8

イニシャライザリスト:

_GLOBAL__sub_I_c:
        sub     rsp, 8
        mov     edi, 10
        call    operator new[](unsigned long)
        mov     edx, 12592
        mov     QWORD PTR c[rip], rax
        mov     WORD PTR [rax], dx
        add     rsp, 8
        ret
c:
        .zero   8

アセンブリは、mov QWORD PTR [rax+2], 0一見ヌル文字でchar配列が終了しているように見える追加の命令を除いて、ほとんど同じです。ただし、IIRCのみの文字列リテラル(など"01")は、char配列リテラルではなく、null文字で自動的に終了します。

生成されたコードが異なる理由と、直接のケースを改善するために私ができること(可能であれば)についての洞察をいただければ幸いです。

また、x86アセンブリに関しては初心者なので、明らかな何かが足りない場合はお知らせください。

編集:文字を追加した場合にのみ悪化します-https://godbolt.org/z/e8Gys_

クルミ

2つのサンプルコードスニペットは同じ効果を持ちません。

new char[10] {'0','1'}

この集約-新しいchar配列を初期化します。つまり、中括弧で囲まれた初期化子リストで初期化子が指定されていない配列のすべての要素がゼロに初期化されます。

x = new char[10];

これにより、新しい配列の要素が値に設定されたり、

std::copy(il.begin(), il.end(), x);

で実際に指定されている要素のみを設定しますstd::initializer_list

したがって、最初のバージョンでは、コンパイラーは、初期化子が指定されていないすべての要素がゼロに設定されることを保証する必要がありますが、2番目のバージョンではこれらの値はそのままにしておくことができます。

新しい式で配列を直接部分的に初期化する方法はありません。しかし、2番目の例の動作の明らかな再現は次のようになります

C() : x(new char[10]) {
    constexpr char t[]{'0','1'};
    std::copy(std::begin(t), std::end(t), x);
}

ただし、実際には、newとにかく直接使用するべきではありません。代わりに使用しstd::vector<char>std::array<char, 10>std::stringまたはstd::unique_ptr<char[]>具体的なユースケースに応じました。これらはすべて、new原因なる生涯の問題を回避します

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

自動関数でconstを使用する場合と使用しない場合のstd :: initializer_list <int>を使用した==テストのC ++ 1z処理

分類Dev

直接初期化と値の初期化

分類Dev

「initializer_list <pair>」と「initializer_list <tuple>」の動作が異なるのはなぜですか?

分類Dev

std :: vectorの効率的な直接初期化

分類Dev

std :: initializer_listが割り当てパラメーターとして使用されている場合、なぜそれが参照型ではないのですか?

分類Dev

なぜstd :: initializer_listを右辺値参照と値で取るのですか?

分類Dev

さまざまな長さのリストのconstリストとしてstd :: initializer_list []を使用する

分類Dev

中括弧表記とinitializer_listを使用する場合、ClangとGCCはコンストラクターの選択に同意しません

分類Dev

std :: initializer_listを使用した明示的なコンストラクターと初期化

分類Dev

初期化による変数の宣言と値を直接使用する

分類Dev

std :: initializer_listコンストラクターと「ブレース初期化」に関する問題

分類Dev

std :: vector :: resizeとゼロへの直接初期化の間に違いはありますか

分類Dev

多次元配列を初期化するためのネストされたinitializer_list

分類Dev

initializer_listを使用して配列を初期化する/ initializer_listをパラメーターパックに変換する

分類Dev

std :: initializer_listをメンバー変数として使用する

分類Dev

std :: initializer_list <std :: string_view>の初期化

分類Dev

std :: initializer_listの初期化がVS2019で失敗するように見えるのはなぜですか

分類Dev

一時的なコピーリストの初期化と直接リストの初期化

分類Dev

コピーの初期化と直接の初期化に違いはありますか?

分類Dev

std :: initializer_listの要素をコピーする必要があるのはなぜですか?

分類Dev

直接初期化ですか、それともコピー初期化ですか?

分類Dev

直接リスト初期化とコピーリスト初期化の違い

分類Dev

C ++がstd :: initializer_listの要素タイプをconstにするのはなぜですか?

分類Dev

std :: minがinitializer_listのみをサポートするのはなぜですか?

分類Dev

ネストされたstd :: initializer_listから2DCスタイルの配列を初期化する方法は?

分類Dev

std :: initializer_listがアイテムをコピーするのはなぜですか?

分類Dev

std :: array <>の初期化

分類Dev

ブレースで囲まれた初期化子の代わりにstd :: initializer_listを使用して配列を初期化できますか?

分類Dev

std :: vectorとstd :: valarrayの初期化コンストラクターが異なるのはなぜですか?

Related 関連記事

  1. 1

    自動関数でconstを使用する場合と使用しない場合のstd :: initializer_list <int>を使用した==テストのC ++ 1z処理

  2. 2

    直接初期化と値の初期化

  3. 3

    「initializer_list <pair>」と「initializer_list <tuple>」の動作が異なるのはなぜですか?

  4. 4

    std :: vectorの効率的な直接初期化

  5. 5

    std :: initializer_listが割り当てパラメーターとして使用されている場合、なぜそれが参照型ではないのですか?

  6. 6

    なぜstd :: initializer_listを右辺値参照と値で取るのですか?

  7. 7

    さまざまな長さのリストのconstリストとしてstd :: initializer_list []を使用する

  8. 8

    中括弧表記とinitializer_listを使用する場合、ClangとGCCはコンストラクターの選択に同意しません

  9. 9

    std :: initializer_listを使用した明示的なコンストラクターと初期化

  10. 10

    初期化による変数の宣言と値を直接使用する

  11. 11

    std :: initializer_listコンストラクターと「ブレース初期化」に関する問題

  12. 12

    std :: vector :: resizeとゼロへの直接初期化の間に違いはありますか

  13. 13

    多次元配列を初期化するためのネストされたinitializer_list

  14. 14

    initializer_listを使用して配列を初期化する/ initializer_listをパラメーターパックに変換する

  15. 15

    std :: initializer_listをメンバー変数として使用する

  16. 16

    std :: initializer_list <std :: string_view>の初期化

  17. 17

    std :: initializer_listの初期化がVS2019で失敗するように見えるのはなぜですか

  18. 18

    一時的なコピーリストの初期化と直接リストの初期化

  19. 19

    コピーの初期化と直接の初期化に違いはありますか?

  20. 20

    std :: initializer_listの要素をコピーする必要があるのはなぜですか?

  21. 21

    直接初期化ですか、それともコピー初期化ですか?

  22. 22

    直接リスト初期化とコピーリスト初期化の違い

  23. 23

    C ++がstd :: initializer_listの要素タイプをconstにするのはなぜですか?

  24. 24

    std :: minがinitializer_listのみをサポートするのはなぜですか?

  25. 25

    ネストされたstd :: initializer_listから2DCスタイルの配列を初期化する方法は?

  26. 26

    std :: initializer_listがアイテムをコピーするのはなぜですか?

  27. 27

    std :: array <>の初期化

  28. 28

    ブレースで囲まれた初期化子の代わりにstd :: initializer_listを使用して配列を初期化できますか?

  29. 29

    std :: vectorとstd :: valarrayの初期化コンストラクターが異なるのはなぜですか?

ホットタグ

アーカイブ