volatile、const、volatile const 和 "neither" 类型之间的转换
Conversions between volatile, const, volatile const, and "neither" types
C++(11) 标准对 volatile、const、volatile const 和 "neither" 类型之间的转换有何规定?我知道将 const 类型分配给非 const 和非 volatile 类型是定义明确且可以接受的,但是在以下类型(其中 T 是某种类型)之间进行转换呢?
// T
T
T volatile
T const
T volatile const
// Pointer-to-T
T*
T volatile*
T const*
T volatile const*
// Volatile pointer-to-T
T* volatile
T volatile* volatile
T const* volatile
T volatile const* volatile
// Const pointer-to-T
T* const
T volatile* const
T const* const
T volatile const* const
// Volatile const pointer-to-T
T* volatile const
T volatile* volatile const
T const* volatile const
T volatile const* volatile const
作为一个简单的例子,请考虑以下代码:
T volatile a;
T const b;
a = b; // implicit conversion from const to volatile; okay?
template<typename T>
void fcn(T& t)
{
t = b; // implicit conversion from const to non-const, which I assume is okay
}
fcn(a); // implicit conversion from volatile to non-volatile; okay?
你能分配给什么?
您始终可以将 volatile 值分配给非常量值。您还可以将 const 和非常量值分配给 volatile 值。您永远不能将任何内容分配给 const 值,因为它们是 const。
是否发生转换?
不 - 它只是在做作业。
这是为什么?
volatile
意味着对对象的任何访问 都无法优化掉 。实际上很少有需要或使用 volatile
的情况。这些案例是:
- 当您对操作进行计时,并且不希望优化计算时(请为此使用基准库。不要自己动手)
- 当你在做内存映射IO的时候。在这种情况下,您希望保证读取和写入不会被优化掉,因此可以使用 volatile。
因此,必须可以将 volatile
分配给常规对象,反之亦然。然而,与此同时,volatile 引用 不应该 隐式转换为常规引用,因为这可能会导致读取和写入被优化。
const呢?
您可以将 const 东西分配给任何东西,但不能将任何东西分配给 const(因为它是 const)。
a = b; // implicit conversion from const to volatile; okay?
是否"okay"取决于类型T
。
这里发生的是左值到右值的转换。标准规则是这样说的:
[conv.lval]
A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed.
If T is a non-class type, the type of the prvalue is the cv-unqualified version of T.
Otherwise, the type of the prvalue is T.
因此,如果例如 T
不是 class 类型,那么从 T const b
转换的纯右值将是 T
,这是相同的在这种情况下作为分配变量的类型。所以,只要 T
是可赋值的(即不是 const),它就是 "okay".
对于class类型,赋值是否为"okay",取决于class有什么样的赋值运算符。隐式赋值运算符不是 volatile 限定的,因此示例赋值将 而不是 是 "okay"。它的格式不正确。但是可以让用户声明一个 volatile 限定赋值运算符,尽管这种情况很少见。
关于 fcn(a); // implicit conversion from volatile to non-volatile; okay?
,根据 this,这是不正确的,因为它会导致从非易失性类型引用易失性类型:
The C Standard, 6.7.3 [ISO/IEC 9899:2011], states
If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
此外,虽然我没有引用,但我相信指针之间的赋值和转换必须具有相同的 volatile-/const- 它们指向的合格类型(即 const
s/ *
之前的 volatile
s 必须匹配):
T volatile* volatile t;
T volatile* volatile const t1 = t; // okay; initializing const with non-const
T* volatile t2 = t; // not okay; t and t2 point to different types
T volatile const* volatile t3 = t; // not okay; t and t3 point to different types
C++(11) 标准对 volatile、const、volatile const 和 "neither" 类型之间的转换有何规定?我知道将 const 类型分配给非 const 和非 volatile 类型是定义明确且可以接受的,但是在以下类型(其中 T 是某种类型)之间进行转换呢?
// T
T
T volatile
T const
T volatile const
// Pointer-to-T
T*
T volatile*
T const*
T volatile const*
// Volatile pointer-to-T
T* volatile
T volatile* volatile
T const* volatile
T volatile const* volatile
// Const pointer-to-T
T* const
T volatile* const
T const* const
T volatile const* const
// Volatile const pointer-to-T
T* volatile const
T volatile* volatile const
T const* volatile const
T volatile const* volatile const
作为一个简单的例子,请考虑以下代码:
T volatile a;
T const b;
a = b; // implicit conversion from const to volatile; okay?
template<typename T>
void fcn(T& t)
{
t = b; // implicit conversion from const to non-const, which I assume is okay
}
fcn(a); // implicit conversion from volatile to non-volatile; okay?
你能分配给什么?
您始终可以将 volatile 值分配给非常量值。您还可以将 const 和非常量值分配给 volatile 值。您永远不能将任何内容分配给 const 值,因为它们是 const。
是否发生转换?
不 - 它只是在做作业。
这是为什么?
volatile
意味着对对象的任何访问 都无法优化掉 。实际上很少有需要或使用 volatile
的情况。这些案例是:
- 当您对操作进行计时,并且不希望优化计算时(请为此使用基准库。不要自己动手)
- 当你在做内存映射IO的时候。在这种情况下,您希望保证读取和写入不会被优化掉,因此可以使用 volatile。
因此,必须可以将 volatile
分配给常规对象,反之亦然。然而,与此同时,volatile 引用 不应该 隐式转换为常规引用,因为这可能会导致读取和写入被优化。
const呢?
您可以将 const 东西分配给任何东西,但不能将任何东西分配给 const(因为它是 const)。
a = b; // implicit conversion from const to volatile; okay?
是否"okay"取决于类型T
。
这里发生的是左值到右值的转换。标准规则是这样说的:
[conv.lval]
A glvalue of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.
因此,如果例如 T
不是 class 类型,那么从 T const b
转换的纯右值将是 T
,这是相同的在这种情况下作为分配变量的类型。所以,只要 T
是可赋值的(即不是 const),它就是 "okay".
对于class类型,赋值是否为"okay",取决于class有什么样的赋值运算符。隐式赋值运算符不是 volatile 限定的,因此示例赋值将 而不是 是 "okay"。它的格式不正确。但是可以让用户声明一个 volatile 限定赋值运算符,尽管这种情况很少见。
关于 fcn(a); // implicit conversion from volatile to non-volatile; okay?
,根据 this,这是不正确的,因为它会导致从非易失性类型引用易失性类型:
The C Standard, 6.7.3 [ISO/IEC 9899:2011], states
If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
此外,虽然我没有引用,但我相信指针之间的赋值和转换必须具有相同的 volatile-/const- 它们指向的合格类型(即 const
s/ *
之前的 volatile
s 必须匹配):
T volatile* volatile t;
T volatile* volatile const t1 = t; // okay; initializing const with non-const
T* volatile t2 = t; // not okay; t and t2 point to different types
T volatile const* volatile t3 = t; // not okay; t and t3 point to different types