为什么在c++中的值初始化中不使用默认构造函数[重复]

问题描述 投票:0回答:1

c++ 底漆说:

只要对象是默认的或 值已初始化。
发生默认初始化
• 当我们定义非静态变量(第 2.2.1 节,第 43 页)或数组(第 3.5.1 节,第 114 页)时 在没有初始化器的块作用域
• 当一个类本身具有类类型的成员时,使用合成的de- 错误构造函数(第 7.1.4,第 262 页)
• 当类类型的成员未在构造函数中显式初始化时 初始化列表(第 7.1.4,第 265 页)
发生值初始化
• 在数组初始化期间,当我们提供的初始值设定项少于大小时 数组的(第 3.5.1 页,第 114 页)
• 当我们定义不带初始化器的局部静态对象时(第 6.1.1 节,第 205 页) • 当我们通过编写表达式显式请求值初始化时 T() 形式,其中 T 是类型的名称(向量构造函数 采用单个参数来指定向量的大小(第 3.3.1 节,第 98 页) 此类参数的值初始化其元素初始值设定项。)
类必须具有默认构造函数才能在这些上下文中使用。最多 这些上下文应该相当明显

class foo{
public :
    int data;
    foo() = default;
};

int main(){
    std::vector<foo> fvec1;
    std::vector<foo> fvec2(4,foo(2));
    foo f[5]{1,2,4};
    std::cout << fvec2[1].data << " " << f[4].data << std::endl;
}

输出:

error: no matching function for call to ‘foo::foo(int)’
    std::vector<foo> fvec2(4, foo(2));
                              ^
error: could not convert ‘1’ from ‘int’ to ‘foo’
       foo f[5]{1,2,4};
                ^

但是如果我们删除以下行

foo() = default;

代码有效,虽然使用了合成的默认构造函数,为什么不将默认构造函数声明为默认值,为什么我虽然声明了默认值但没有获得默认行为。
如果可能的话,任何人都可以提供“c++ Primer”所说的上述原因的示例,因为它太令人困惑了。

标准:C++ 20
编译器:g++-12,clang++-15

c++ default-constructor value-initialization default-initialization
1个回答
1
投票

我们这里发生了一些事情。首先是

foo
,形式为

class foo{
public :
    int data;
};

是一个聚合。聚合可以使用

{}
进行初始化,并从 C++20 开始,已扩展为包含
()
进行初始化。这意味着在

std::vector<foo> fvec2(4,foo(2));
//and
foo f[5]{1,2,4}

您聚合初始化对象。

当您将

foo
更改为

class foo{
public :
    int data;
    foo() = default;
};

您不再拥有聚合,因为您有用户声明的构造函数。这意味着要对其进行值初始化,您需要提供一个构造函数,该构造函数接受构造该类所需的值。您可以通过添加像

这样的构造函数来做到这一点
class foo{
public :
    int data;
    foo() = default;
    foo(int data_) : data(data_) {}
};
© www.soinside.com 2019 - 2024. All rights reserved.