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

时间:2017-09-17 12:21:57

标签: c++ casting static-cast

以下是两个非常相似的片段:

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是否安全?

3 个答案:

答案 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 datawarning: 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 ++标准允许它)