对于在C ++ 11和C ++ 17中调用构造函数的方式/原因,我有些困惑。
#include <iostream>
using namespace std;
//---
template<typename T>
struct StructTest
{
public:
const T Var = -1;
//---
// constexpr StructTest() = delete; // 1
// constexpr StructTest() = default; // 2
// constexpr StructTest(const StructTest &Source) = delete; // 3
// constexpr StructTest(const StructTest &Source) = default; // 4
// constexpr StructTest(const StructTest &Source) {cout << "Copy" << endl;}; // 5
};
//---
StructTest<int> A{};
StructTest<int> A1{1};
StructTest<int> A2(A);
//---
int main(void)
{
return(0);
};
因此,当我取消注释某些行组合(并使用clang的c ++ 17标准标志进行编译)时,我会感到困惑:
A
和A1
的初始化,以及A2
的默认副本构造函数A
和列表init A1
(?)的默认构造函数,以及A2的默认副本构造函数A2
的副本构造函数已删除而无法编译A
的默认构造函数和列表init A1(?),以及A2
的默认副本构造函数A
和列表init A1
(?)的默认构造函数,以及A2的默认副本构造函数A
缺少(删除)默认构造函数,并且A1
没有匹配的构造函数?A1
没有匹配的构造函数?我想我大部分都明白,但是我很困惑为什么1 + 5和2 + 5编译失败。谁能解释编译器用来选择将要使用的构造函数的逻辑,以及为什么编译失败?
如果在其他情况下我认为正在调用的构造函数是错误的,您还能指出正在调用的是什么,为什么?
答案 0 :(得分:9)
1,编译。列出A和A1的init,以及A2的默认复制构造函数
在这种情况下,您称为 List init 的实际上是aggregate initialization,因为StructTest
是一个聚合。之所以允许这样做,是因为存在显式默认或已删除的构造函数仍然会使该类成为聚合类。
2,编译。 A的默认构造函数和列表初始化A1?,A2的默认副本构造函数
A1
像1中发生的一样被聚合初始化。其余的都正确
1 + 3或2 + 3,由于A2的副本构造函数已删除而无法编译
这是预期的行为,因为复制构造函数被标记为已删除。
1 + 4,编译。 A的默认构造函数和列表初始化A1?,A2的默认副本构造函数
再次A
和A1
的聚合初始化
2 + 4,编译。 A的默认构造函数和列表初始化A1?,A2的默认副本构造函数
A
和A1
将被聚合初始化,但在按[dcl.init.aggr]/5.1初始化Var
时将使用默认成员初始化器A
1 + 5,无法编译。说A缺少(删除)了默认构造函数,而A1没有匹配的构造函数?
5是用户提供的非默认或删除的构造函数。这意味着StructTest
不再是聚合,您不能再对其进行初始化。
2 + 5,无法编译。没有匹配的A1构造函数?
原因与1 + 5
答案 1 :(得分:5)
(这是其他答案的附加信息)
对于C ++ 11,C ++ 14/17和C ++ 20,此代码的行为是不同的!由于 aggregate 的定义不断变化。
在C ++ 11中,该类不是集合,因为它具有括号或相等的初始化器(= -1
),因此情况1无法编译。
在C ++ 14和17中,该类是一个聚合,其他答案涵盖了这种情况。
在C ++ 20中,该类将不再是聚合,因为存在一条新规则,即任何用户声明的构造函数都将使该类不具有聚合资格;因此情况1将停止再次编译,在情况2中,StructTest<int> A1{1};
由于构造函数的参数过多等原因将无法编译。
答案 2 :(得分:3)
您所说的list init
实际上称为聚合初始化。在所有情况下,您的课程都是合计的,但是当您取消第5行的注释时-此时,它不再是合计的。聚合类是 all 构造函数被默认(显式或隐式)或删除的类。您只有一个非默认的,未删除的构造函数,因此,除非您取消注释,否则您的类仍然是聚合的。
考虑到这一点,您的大多数示例都围绕聚合初始化,除非您通过删除copy-constructor或添加非默认的copy-constructor来显式禁止复制,并使类变为非聚合。
有关聚合和聚合初始化的更多信息:https://en.cppreference.com/w/cpp/language/aggregate_initialization