C++ 中数字类型转换的最佳实践
Best practice in C++ for casting between number types
在不同数字类型之间进行转换的最佳做法是什么?类型 float
、double
、int
是我在 C++ 中使用最多的类型。
选项示例,其中 f
是 float
,n
是 double
或 int
:
float f = static_cast<float>(n);
float f = float(n);
float f = (float)n;
我通常写 static_cast<T>(...)
但想知道 C++ 开发社区是否有任何共识是否有更好的方式。
我明白这可能最终会成为一个基于意见的问题并且可能没有 "standard" 方式,在这种情况下请告诉我没有标准方式所以至少我知道: -)
我知道这个问题 cropped up 与一般转换有关,但是,我对数字特别感兴趣,以及在数字类型的方法中是否有特定的最佳实践。
只需使用static_cast
。 C 转换的问题是操作的歧义(即 Explicit type conversion 的第 (1) 点)。
C++ 转换避免了这种情况。此外,在搜索 C++ 强制转换时会更加明显。
用 Stroustrup 的话 (What good is static_cast?):
Even an innocent-looking cast can become a serious problem if, during development or maintenance, one of the types involved is changed. For example, what does this mean?:
x = (T)y;
We don't know. It depends on the type T
and the types of x and y. T
could be the name of a class, a typedef
, or maybe a template parameter. Maybe x
and y
are scalar variables and (T)
represents a value conversion. Maybe x
is of a class derived from y
's class and (T)
is a downcast. Maybe x
and y
are unrelated pointer types. Because the C-style cast (T)
can be used to express many logically different operations, the compiler has only the barest chance to catch misuses. For the same reason, a programmer may not know exactly what a cast does. This is sometimes considered an advantage by novice programmers and is a source of subtle errors when the novice guessed wrong.
The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors.
[CUT]
A secondary reason for introducing the new-style cast was that C-style casts are very hard to spot in a program. For example, you can't conveniently search for casts using an ordinary editor or word processor.
[CUT]
casts really are mostly avoidable in modern C++
同时考虑 boost::numeric::converter
/ boost::numeric_cast
that are safer alternatives (part of 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
在转换数字类型时检测范围丢失,如果无法保留范围则抛出异常。
通常,这些转换运算符分为两大类:
特定的转换运算符 和传统的转换运算符。 cplusplus.com 解释如下:
...In order to control these types of conversions between classes, we have four specific casting operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new_type) expression
new_type (expression)
but each one with its own special characteristics.
在处理任务时,我们(几乎)都使用特定的转换。在考虑了这些建议之后,这取决于你。
参见resource。
在不同数字类型之间进行转换的最佳做法是什么?类型 float
、double
、int
是我在 C++ 中使用最多的类型。
选项示例,其中 f
是 float
,n
是 double
或 int
:
float f = static_cast<float>(n);
float f = float(n);
float f = (float)n;
我通常写 static_cast<T>(...)
但想知道 C++ 开发社区是否有任何共识是否有更好的方式。
我明白这可能最终会成为一个基于意见的问题并且可能没有 "standard" 方式,在这种情况下请告诉我没有标准方式所以至少我知道: -)
我知道这个问题 cropped up 与一般转换有关,但是,我对数字特别感兴趣,以及在数字类型的方法中是否有特定的最佳实践。
只需使用static_cast
。 C 转换的问题是操作的歧义(即 Explicit type conversion 的第 (1) 点)。
C++ 转换避免了这种情况。此外,在搜索 C++ 强制转换时会更加明显。
用 Stroustrup 的话 (What good is static_cast?):
Even an innocent-looking cast can become a serious problem if, during development or maintenance, one of the types involved is changed. For example, what does this mean?:
x = (T)y;
We don't know. It depends on the type
T
and the types of x and y.T
could be the name of a class, atypedef
, or maybe a template parameter. Maybex
andy
are scalar variables and(T)
represents a value conversion. Maybex
is of a class derived fromy
's class and(T)
is a downcast. Maybex
andy
are unrelated pointer types. Because the C-style cast(T)
can be used to express many logically different operations, the compiler has only the barest chance to catch misuses. For the same reason, a programmer may not know exactly what a cast does. This is sometimes considered an advantage by novice programmers and is a source of subtle errors when the novice guessed wrong.The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors.
[CUT]
A secondary reason for introducing the new-style cast was that C-style casts are very hard to spot in a program. For example, you can't conveniently search for casts using an ordinary editor or word processor.
[CUT]
casts really are mostly avoidable in modern C++
同时考虑 boost::numeric::converter
/ boost::numeric_cast
that are safer alternatives (part of 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
在转换数字类型时检测范围丢失,如果无法保留范围则抛出异常。
通常,这些转换运算符分为两大类: 特定的转换运算符 和传统的转换运算符。 cplusplus.com 解释如下:
...In order to control these types of conversions between classes, we have four specific casting operators: dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new_type) expression
new_type (expression)
but each one with its own special characteristics.
在处理任务时,我们(几乎)都使用特定的转换。在考虑了这些建议之后,这取决于你。
参见resource。