これは古いC ++スタイルのコンストラクタですか?


17

ここにC ++コードの一部があります。

この例では、多くのコードブロックがコンストラクター呼び出しのように見えます。残念ながら、ブロックコード#3はそうではありません(https://godbolt.org/z/q3rsxnhttps://cppinsights.ioを使用して確認できます)。

これは古いC ++表記であり、{}を使用した新しいC ++ 11構成表記の導入を説明できると思います(#4を参照)。

T(i)意味の説明はありますか?コンストラクタの表記にとても近いですが、間違いなくとても違いますか?

struct T {
   T() { }
   T(int i) { }
};

int main() {
  int i = 42;
  {  // #1
     T t(i);     // new T named t using int ctor
  }
  {  // #2
     T t = T(i); // new T named t using int ctor
  }
  {  // #3
     T(i);       // new T named i using default ctor
  }
  {  // #4
     T{i};       // new T using int ctor (unnamed result)
  }
  {  // #5
     T(2);       // new T using int ctor (unnamed result)
  }
}

注意:したがって、T(i)(#3)はと同等T i = T()です。


1
あなたの発言はすべて正しいと思います。
Arne J


追加:コンパイラは、あなたがそれを求めるなら、あなたが知っておく必要があるほとんどすべてを教えてくれることに注意-Wallして、あなたが得るwarning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'i' [-Wvexing-parse]」打ち鳴らすから、またはわずかに少ないやる気「warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]GCCから
Max Langhof

@QuentinUKこのリンクをありがとう。関数(などT t())については知っていましたが、それほど単純な宣言式についてはそうではありませんでした。確かに、これは厄介なことかもしれませ
Pascal H.

回答:


17

ステートメント:

T(i);

以下と同等です。

T i;

つまり、itype という名前の変数を宣言していますT。これは、(宣言子のバインディングを変更するために)一部の場所の宣言で括弧が許可されているためであり、このステートメントは宣言として解析できるため、それは宣言です(式としてより意味があるかもしれませんが)。


それで、これint(i)int名前付きも宣言するC仕様から継承された解釈の選択だけiですか?
Pascal H.

@PascalH。特定の観点から、それは本当である可能性があります。StroustrupはD&Eで、C ++の代替の、より直感的な宣言構文を検討したと書いています。C ++がCと下位互換性を持つ必要がなかった場合、おそらく代替構文があり、式とのあいまいさの可能性を回避します。
ブライアン、

-1

コンパイラー・エクスプローラーを使用して、アセンブラーで何が発生するかを確認できます。

#1、#2、#4、および#5は同じことを行いますが、#3が他のコンストラクター(ベースオブジェクトコンストラクター)を呼び出していることがわかります。

誰か説明がありますか?

アセンブラコード:

::T() [base object constructor]:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        nop
        pop     rbp
        ret
T::T(int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 42
// #1
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-7]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #2
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-8]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #3
        lea     rax, [rbp-9]
        mov     rdi, rax
        call    T::T() [complete object constructor]
// #4
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-6]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #5
        lea     rax, [rbp-5]
        mov     esi, 2
        mov     rdi, rax
        call    T::T(int)

        mov     eax, 0
        leave
        ret

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.