在本视频的结尾(从 15:57 开始),提供了有关如何在 C++17 中使用几乎统一初始化的建议:此处的视频
要点是这样的:始终使用直接初始化auto a{...};
,MyType a{...};
不要= {...}
对您的类型使用复制初始化。
#include <iostream>
struct MyType {
explicit MyType(std::initializer_list<int>) {
std::cout << "Called std::initializer_list<int>" << std::endl;
}
explicit MyType(int) {
std::cout << "Called int." << std::endl;
}
MyType(int, int, int) {
std::cout << "Called int, int, int" << std::endl;
}
};
int main() {
MyType calls_init_list{10}; //Calls initializer_list<int>
MyType calls_init_list_2{10, 20}; //Calls initializer_list<int>
MyType calls_init_list_3{10, 20, 30}; //Calls initializer_list<int>
MyType compile_error = {10, 20, 30}; //Compile error
}
如果我从第一个构造函数中删除显式,它也会调用第四个调用 initializer_list<int>
(int)
并(int, int, int)
遵守视频中的规则?我需要进行哪些更改才能按照视频中的规则调用 (int) 和 (int, int, int)?
删除initializer_list<int>
构造函数。这是让它发挥作用的唯一方法。
在初始化列表构造函数存在的情况下甚至可以调用其他构造函数吗?
是的,只要括号初始化列表中的类型不能匹配任何initializer_list<T>
构造函数中的类型。他们始终处于领先地位。
这就是为什么它被嘲笑地称为“几乎一致的初始化”。
典型的解决方案是在非initializer_list
构造函数中添加一些标签类型:
struct tag_t {};
constexpr inline tag_t tag;
struct MyType {
explicit MyType(std::initializer_list<int>) {
std::cout << "Called std::initializer_list<int>" << std::endl;
}
MyType(tag_t, int) {
std::cout << "Called int." << std::endl;
}
MyType(tag_t, int, int, int) {
std::cout << "Called int, int, int" << std::endl;
}
};
int main() {
MyType three_int = {tag, 10, 20, 30}; //Calls 3-`int` constructor
}
有什么设计建议可以避免放弃视频中建议的一般规则?
好吧,考虑到“一般规则”不是一个好的规则(他的幻灯片包含典型的反例:尝试调用vector<int>
with 大括号的 size+value 版本),最好放弃它。除了auto a{2};
字面上无法调用某些构造函数之外,关于翻译成什么的小争论是无关紧要的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句