我应该在赋值和 return 语句中使用 static_cast 吗?为什么?

Should I use static_cast in assignments and return statements and why?

这里有两个非常相似的片段:

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 则隐式应用相同的转换。

这种隐式转换属于哪种类型?在显式赋值和 return 语句中省略 static_cast 是否安全?

这将是一个积分转换。还有一个缩小的。

对于变量初始化,如果你想要一个特定的类型,一个好的方法是按照 Herb Sutter 在他的 "Almost Always Auto" GotW article:

中的建议
auto n = int{a.size()};

尽可能使用列表初始化。它将阻止缩小转换,并且编译器会在需要时将您标记为使用显式转换(例如上述情况)。

铸造的必要性取决于转换的必要性。所以这里真正的问题应该 "be why would I return / store an int instead of vector<int>::size_type?" 如果你的程序逻辑并不真的需要这样的转换那么根本就不要执行它。如果您的程序逻辑需要这样的转换(例如,您需要将此值传递给对接受 int 的第三方函数的调用),那么您应该使用 static_cast。在这种情况下省略 static_cast 将是意外缩小转换的标志,并将触发相应的编译器警告,例如 warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of datawarning: conversion to 'int' from 'std::vector<int>::size_type {aka long unsigned int}' may alter its value [-Wconversion]

这个转换不是那么安全,实际上 n 的值可能是实现定义的(c++ 标准 [conv.integral]):

If the destination type is signed, the value is unchanged if it can be represented in the destination type otherwise, the value is implementation-defined.

如果您启用所有警告,并且不使用 static_cast,您的编译器可能会通知您缩小转换。如果您使用 static_cast,您会告知 reader 您的代码,您确定 a.size() <= std::numeric_limits<int>::max() 或者您知道如果这样的条件不成立,您的实现将要做什么。

(请注意,如果 std::size_t 小于 int,则之前的比较也可能调用实现定义的转换,c++ 标准允许这样做)