【问题标题】:Best practice in C++ for casting between number types [duplicate]C ++中数字类型之间转换的最佳实践[重复]
【发布时间】:2016-09-26 14:13:09
【问题描述】:

在不同数字类型之间进行转换的最佳做法是什么? floatdoubleint 类型是我在 C++ 中使用最多的类型。

ffloatndoubleint 的选项示例:

float f = static_cast<float>(n);
float f = float(n);
float f = (float)n;

我通常写static_cast&lt;T&gt;(...),但想知道如果有首选方式,C++ 开发社区内是否有任何共识。

我很欣赏这最终可能是一个基于意见的问题,并且可能没有“标准”方式,在这种情况下,请告诉我没有标准方式,所以至少我知道 :-)

我知道这个问题有cropped up 与一般转换有关,但是,我特别感兴趣的是数字以及数字类型的方法中是否有特定的最佳实践。

【问题讨论】:

  • 使用 static_cast,“标准”C++ 方式,与 C++11 相比没有任何改变。
  • 最好的做法是编写一个不需要任何强制转换的程序
  • 这在 C++11 中没有改变;与该标准的早期版本相同的规则适用。有关详细信息,请参阅链接的重复问题,以及 this one
  • @Cody Gray,我的问题是针对 numbers 的,我相信其他人可能有兴趣了解一般情况是否适用。我并不是真的要暗示我在推测 C++ 11 是否与早期版本不同。
  • @Drop,仅当您从头开始编写代码并且第三方库之间没有类型差异并且您没有使用 double 来获得准确性然后浮动进行矢量化以及许多其他原因时才有效为什么数字之间的转换在科学计算中非常典型。

标签: c++ casting numeric-conversion


【解决方案1】:

只需使用static_cast。 C 类型转换的问题在于操作的模糊性(即Explicit type conversion 的第 (1) 点)。

C++ 强制转换避免了这种情况。此外,C++ 类型转换在搜索它们时更加明显。

用 Stroustrup 的话 (What good is static_cast?):

如果在开发或维护期间,其中一种类型发生了变化,即使是看起来很无辜的演员表也会成为一个严重的问题。例如,这是什么意思?:

  x = (T)y;

我们不知道。这取决于T 的类型以及x 和y 的类型。 T 可以是类的名称、typedef 或模板参数。也许xy 是标量变量,(T) 代表值转换。也许x 是从y 的类派生的一个类,而(T) 是一个向下转型。也许xy 是不相关的指针类型。因为 C 风格的转换 (T) 可用于表达许多逻辑上不同的操作,所以编译器只有极少的机会来发现误用。出于同样的原因,程序员可能不知道强制转换的确切作用。这有时被新手程序员认为是一种优势,并且当新手猜错时会导致细微错误。

引入“新式强制转换”是为了让程序员有机会更清楚地表达他们的意图,并让编译器捕捉更多错误。

[剪切]

引入新风格转换的第二个原因是 C 风格转换很难在程序中发现。例如,您不能使用普通的编辑器或文字处理器方便地搜索演员表。

[剪切]

在现代 C++ 中确实可以避免强制转换

还要考虑 boost::numeric::converter / boost::numeric_cast 是更安全的替代方案(Boost.NumericConversion 库的一部分)。

例如

#include <iostream>
#include <boost/numeric/conversion/cast.hpp>

int main()
{
  using boost::numeric_cast;

  using boost::numeric::bad_numeric_cast;
  using boost::numeric::positive_overflow;
  using boost::numeric::negative_overflow;

  try
  {
    int i = 42;
    short s = numeric_cast<short>(i); // This conversion succeeds (is in range)
  }
  catch(negative_overflow &e)  { std::cout << e.what(); }
  catch(positive_overflow &e)  { std::cout << e.what(); }

  return 0;
}

一般来说,对于隐式转换和显式转换(通过static_cast),缺少范围保存会导致数值类型之间的转换容易出错。

numeric_cast 在数值类型转换时检测范围丢失,如果范围不能保留,则抛出异常。

【讨论】:

  • 有时它是一个转换......有时它是一个演员”对我来说没有多大意义。强制转换是显式转换,不是吗?。
  • @user2079303 你是对的:它是“Google 的术语”(google.github.io/styleguide/cppguide.html#Casting),但它与常规 C++ 用法(stackoverflow.com/q/4337306/3235496)不完全匹配。我已经改变了这条线以避免误解。
  • 感谢您的链接。当我将来偶然发现该术语时,它会有所帮助。太糟糕了,该指南没有用术语解释演员表和转换之间的区别。
  • @manlio 如果 boost 不是一个选项,这里是 boost::numeric_cast 的重新实现,仅使用 std 库中可用的代码:stackoverflow.com/a/49658950/52074
【解决方案2】:

通常,这些铸造操作员分为两大类: 特定的铸造运营商传统铸造运营商cplusplus.com 是这样解释的:

...为了控制类之间的这些类型的转换,我们有四个特定的转换运算符:dynamic_cast、reinterpret_cast、static_cast 和 const_cast。它们的格式是遵循用尖括号 () 括起来的新类型,紧随其后的是要在括号之间转换的表达式。

dynamic_cast &lt;new_type&gt; (expression)

reinterpret_cast &lt;new_type&gt; (expression)

static_cast &lt;new_type&gt; (expression)

const_cast &lt;new_type&gt; (expression)

这些表达式的传统类型转换等价物是:

(new_type) expression

new_type (expression)

但每一种都有自己的特点。

在处理一项任务时,我们(几乎)都使用特定的演员表。在考虑了这些建议之后,这取决于你。

请参阅resource

【讨论】:

    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 2015-09-26
    相关资源
    最近更新 更多