以下是两个非常相似的片段:
vector<int> a;
int n = static_cast<int>(a.size());
// ---------
int f(const vector<int>& a) {
return static_cast<int>(a.size());
}
在这里,我明确地将类型size_t
的值转换为int
类型。如果我省略static_cast
,则隐含地应用相同的演员表。
这种隐式演员会是哪种?在显式赋值和返回语句中省略static_cast
是否安全?
答案 0 :(得分:3)
这将是一个完整的转换。在那个缩小的那个。
对于变量初始化,如果你想要一个特定的类型,一个好的方法是做Herb Sutter在他的&#34;几乎总是自动&#34; GotW article:
auto n = int{a.size()};
尽可能使用列表初始化。它可以防止缩小转换,并且您的编译器会在需要时标记它以使用显式转换(例如上面的情况)。
答案 1 :(得分:2)
铸造的必要性取决于转换的必要性。所以真正的问题应该是“为什么我会返回/存储int
而不是vector<int>::size_type
?”如果您的程序逻辑确实不需要这样的转换,那么根本不执行它。如果您的程序逻辑需要这样的转换(例如,您需要将此值传递给对接受int
的第三方函数的调用),那么您应该使用static_cast
。在这种情况下省略static_cast
将表明意外缩小转化并触发相应的编译器警告,例如warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data
或warning: conversion to 'int' from 'std::vector<int>::size_type {aka long unsigned int}' may alter its value [-Wconversion]
答案 2 :(得分:1)
此演员表不安全,实际上n
的值可能是实现定义的(c ++标准[conv.integral]):
如果目标类型已签名,则该值如果可以在目标类型中表示,则不会更改,否则,该值是实现定义的。
如果您启用了所有警告,并且未使用static_cast,则编译器可能会通知您有关缩小转换的信息。如果您使用static_cast
,则会告知读者您确切知道的代码a.size() <= std::numeric_limits<int>::max()
或您知道如果不满足这样的条件,您的实现将会执行的操作。
(请注意,如果std :: size_t小于int,则先前的比较也可能调用实现定义的转换,c ++标准允许它)