提问人:AnonA 提问时间:8/23/2023 最后编辑:AnonA 更新时间:8/23/2023 访问量:57
C++:尽管有显式构造函数,但大括号初始化
C++: Curly Braces Initialization Despite Explicit Constructor
问:
我有一个数据类(就像 C 意义上的结构:一个只有一堆属性的类),我用来用大括号初始化初始值设定项列表(我认为是通过隐式复制构造函数),如下所示:
ClassName inst = {1, 2, 3, 4};
然后我决定要从向量启用初始化,所以我定义了一个看起来像这样的 ctor:
ClassName(std::vector<int> vec) : A(vec[0]), B(vec[1]), C(vec[2]), D(vec[3]) {}
但是,自从添加此构造函数以来,由于“无法从'初始值设定项列表'转换为'namespace::ClassName'”,上面引用的大括号初始化方法不再有效。
我尝试在谷歌上搜索解释/建议/解决方案,但找不到正确的关键字,而且我似乎没有找到任何确切的答案。
您如何建议解决这个问题(无论是具体如何重新启用此类列表初始化,还是在设计方面,如果我应该以某种方式避免这种情况)?
答:
添加用户定义的构造函数后,您的类不再是聚合类型(假设它以前是聚合类型,因为您的问题不完整),因此列表初始化的最后一条规则适用:
否则,将分两个阶段考虑 T 的构造函数:
(...)
如果上一阶段未产生匹配项,则 T 的所有构造函数都参与针对由 braced-init-list 的元素组成的参数集的重载解析,但限制是只允许非缩小转换。(...).
因此,编译器尝试传递 4 个类型的参数,而您的构造函数需要 1 个类型的参数。如果您改为像这样初始化实例int
std::vector<int>
ClassName inst = {{1, 2, 3, 4}};
编译器将选择预期的 1 参数构造函数,然后转换为使用其构造函数,并采用 .std::vector<int>
{1, 2, 3, 4}
std::vector<int>
initializer_list
评论
initializer_list
请考虑以下三个类:
#include <vector>
#include <initializer_list>
struct aggregate {
int a,b,c,d;
};
struct non_aggregate {
int a,b,c,d;
non_aggregate(std::vector<int>) {}
};
struct init_list_constr {
int a,b,c,d;
init_list_constr(std::initializer_list<int>) {}
};
int main() {
aggregate a = {1,2,3,4};
//non_aggregate b = {1,2,3,4}; // error
init_list_constr c = {1,2,3,4};
}
aggregate
是一个聚合,因为它没有用户定义的构造函数。您可以使用聚合初始化: 。 不是聚合,因为它具有用户定义的构造函数,并且不能使用聚合初始化。aggregate a = {1,2,3,4};
non_aggregate
我建议你提供一个构造函数,它也可以使用用户定义的构造函数进行聚合初始化。std::initializer_list
有关详细信息,我建议您 https://en.cppreference.com/w/cpp/language/aggregate_initialization
评论
init_list_constr c = {1,2,3,4};
评论
std::vector
std::span
ClassName
std::span