初始化程序列表语法的一个明显优点是,它通过禁止缩窄转换来提高类型安全性。
int x {7.9}; // error: narrowing
int y = 7.9; // OK: y becomes 7. Hope for a compiler warning然而,AFAIK没有办法在随后的转让中强制执行相同的检查:
int z {7};
z = 7.9; // allows narrowing, and no other syntax available为什么初始化时的类型安全受到语言设计的更多关注,而在赋值过程中类型安全性更高呢?任务的缩小是否不太可能导致错误和/或更难检测?
发布于 2017-07-03 12:11:48
如果x是int变量,那么
x = 7.9;由于向后兼容性的原因,必须在C++11和以后继续工作。即使x是大括号初始化的,情况也是如此。大括号初始化的int变量与非大括号初始化的int变量具有相同的类型.如果通过引用函数传递x,
void f(int& r);
f(x);然后,在f的主体中,将无法“判断”对象是否已被大括号初始化,因此该语言不能对其应用不同的规则。
您可以通过这样做来防止自己缩小转换:
x = {7.9}; // error还可以尝试通过创建不允许缩小分配的int“包装器”类型来利用类型系统:
struct safe_int {
template <class T> safe_int(T&& x) : value{std::forward<T>(x)} {}
template <class T> safe_int& operator=(T&& x) {
value = {std::forward<T>(x)}; return *this;
}
operator int() const { return value; }
int value;
};不幸的是,不能使该类在任何情况下都像实际的int对象那样运行。
发布于 2017-07-03 12:14:38
为什么初始化时的类型安全受到语言设计的更多关注,而在赋值过程中类型安全性更高呢?
不,这不是原因,是列表初始化给了您错误,例如,这也会出错:
int x = {7.8};这是因为根据dcl.init,列表初始化中不允许缩小范围。
如果初始化-子句是表达式,并且转换表达式需要收缩转换,则程序的格式不正确。
发布于 2017-07-03 12:14:34
{}防止转换类型,例如double到int,但是
()可以这样做,只能显示有关转换的警告。
你可以这样写
int z(7.9) // == 7
当您确信类中不存在带有std::initializer_list的构造函数时,可以使用括号,因为他将被执行,或者您可以delete该构造函数。
https://stackoverflow.com/questions/44885143
复制相似问题