C++ 对象实例化 - 当使用空括号实例化对象时调用哪个构造函数

C++ Object Instantiation - Which constructor is called when an object is instantiated using empty parenthesis

我对用于实例化对象的不同语法感到困惑。

这是我的 class:

class Object
{

private:

    int field = 0;

public:

    Object() = default; // Just for testing.
    ~Object() = default; // Just for testing.

    Object( const Object& obj ) = default; // Just for testing.

};

这是主要方法:

int main()
{
    Object b(); // ???
    Object c{}; // default
    Object d = Object(); // default
    Object e = Object{}; // default
    Object f ( Object() ); // ???
    Object g { Object() }; // default
    Object a; // default but avoid
    Object h ( Object() ); // ???
    Object i { Object{} }; // default
    Object j = i; // copy
    Object k( j ); // copy
    Object l{ k }; // copy
    Object m = { l }; // copy
    Object n = ( m ); // copy
    auto o = Object(); // default
    auto p = Object{}; // default
    return 0;
}

我对标记为 defaultcopy 的没有问题。我只想知道,哪个构造函数被调用为 ??? 的构造函数,因为没有调用默认构造函数。跟()初始化有关系吗,可以看出

我知道这可能不重要,但我对此持怀疑态度。

谁能帮忙!

这三个声明都是函数声明,而不是变量定义(如您所料)。

Object b(); 声明了一个名为 b 的函数,它不带任何参数 returns Object.

Object f ( Object() ); 声明了一个名为 f 的函数,它接受一个未命名的参数,该参数的类型是一个函数返回 Object 并且不带任何参数(即 Object()),并且 returns ObjectObject h ( Object() );.

同样

作为解决方法,Object b(); 您可以

Object b;
Object b{}; // since C++11

对于 Object f ( Object() ); 你可以

Object f ( ( Object() ) );
Object f ( Object{} );     // since C++11
Object f { Object{} };     // since C++11
Object f { Object() };     // since C++11

有关更多信息,请参阅 most vexing parse

它实际上没有调用任何构造函数。

当您更改对象 class 以便所有字段都是 public(以便您可以查看它们)时:

#include <iostream>
class Object
{
public:
    int field = 0;
    Object() = default;
    ~Object() = default;
    Object( const Object& obj ) = default;
};

然后你尝试调用main方法中的空括号:

int main()
{
    Object b();
    std::cout << b.field << '\n';
    return 0;
}

你得到一个错误,因为 b 不是一个对象而是一个函数:

错误:请求'b'中的成员'field',它是非class类型'Object()'

这就是为什么当你想调用空括号构造函数时,你必须在没有任何括号的情况下调用它:

int main()
{
    Object b;    // this is correct
    std::cout << b.field << '\n';
    return 0;
}

您正确识别了所有构造函数。你不确定的三个不要按照你的想法去做

Object b();
Object f ( Object() );
Object h ( Object() );

所有这些都是函数声明,而不是变量定义。

您声明了一个函数 b,它没有参数并且 return 是一个 Object。然后声明两个函数,fh,它们有一个未命名的参数和 return 和 Object。参数类型为:无参函数,returning Object.

这就是所谓的most vexing parse。基本上 C++ 标准说:“如果它可以被解析为函数声明,则它必须被解析为函数声明。” Clang 甚至有一个警告:-Wvexing-parse.