这是旧的C ++样式构造函数吗?


17

这里是一段C ++代码。

在此示例中,许多代码块看起来像构造函数调用。不幸的是,第3块代码不是(您可以使用https://godbolt.org/z/q3rsxnhttps://cppinsights.io进行检查)。

我认为,这是一种古老的C ++表示法,它可以解释使用{}(参见#4)引入新的C ++ 11构造表示法的方法。

您是否有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并从clang中获取warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'i' [-Wvexing-parse]”,或者从gcc中获得动力较少的“ warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]” 。
Max Langhof

@QuentinUK感谢您提供此链接。我了解到有关函数(例如T t())的信息,但没有这么简单的声明表达式。当然,这可能很烦人
Pascal H.19年

Answers:


17

该声明:

T(i);

等效于:

T i;

换句话说,它声明了一个名为itype 的变量T。这是因为某些地方的声明中允许使用括号(以更改声明符的绑定),并且由于此语句可以被解析为声明,所以它是一个声明(即使作为表达式可能更有意义)。


那么,这仅仅是从C规范继承int(i)而又声明了intnamed 的解释选择i吗?
Pascal H.19年

@PascalH。从某种角度来看,这可能是正确的。Stroustrup在D&E中写道,他已经考虑了C ++的另一种更直观的声明语法。如果C ++不必与C向后兼容,则它可能具有替代语法,从而避免了表达式的潜在歧义。
布莱恩

-1

您可以使用Compiler Explorer查看汇编器中发生的情况。

您可以看到#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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.