C++ c++;访问一次
我正试图在c++11中实现与Linux宏ACCESS\u ONCE相当的功能。C++ c++;访问一次,c++,c++11,C++,C++11,我正试图在c++11中实现与Linux宏ACCESS\u ONCE相当的功能。 ACCESS\u ONCE(x)获取x的地址,将其强制转换为指向与x相同类型的volatile的指针,然后取消引用它。这迫使编译器不通过该宏优化对x的访问(并使访问在此仅发生一次) 我试图在c++11中实现这一点,涉及到decltype: #define ACCESS_ONCE(x) (*static_cast<decltype(x) volatile *>(&(x))) 此操作失败并出现错误:
ACCESS\u ONCE(x)
获取x的地址,将其强制转换为指向与x相同类型的volatile的指针,然后取消引用它。这迫使编译器不通过该宏优化对x的访问(并使访问在此仅发生一次)
我试图在c++11中实现这一点,涉及到decltype
:
#define ACCESS_ONCE(x) (*static_cast<decltype(x) volatile *>(&(x)))
此操作失败并出现错误:
'volatile' qualifiers cannot be applied to 'void*&'
我做错了什么?将宏更改为:
#define ACCESS_ONCE(x) (*static_cast<std::remove_reference<decltype(x)>::type volatile *>(&(x)))
#定义一次访问(x)(静态(x))
取消对指针的引用将导致引用。宏试图将其强制转换为void*&volatile
而不是您想要的void*volatile
。无法将volatile限定符应用于引用类型,因此必须使用std::remove\u reference将其更改为正常的非引用类型。模板
template<typename T>
inline T volatile &access_once(T &t) {
return static_cast<T volatile &>(t);
}
内联T易失性和一次性访问(T&T){
返回静态_-cast(t);
}
这避免了宏,更简单,因为类型推断和引用删除在模板签名中是隐式的,并且它避免了冗余的地址和差异运算符(引用类型之间的静态转换定义为执行与获取地址、转换然后取消引用相同的操作)。它的性能也一样,我不认为这取决于C++11中的任何内容。非常感谢。这就解决了问题,并教会了我一些c++11技巧。避免宏——它们是为c黑客准备的。这里正确的强制转换是
const_cast
,尽管它的名称不同,它可以添加和删除volatile
限定符以及const
限定符。@PeteBecker我不同意<代码>静态_cast是这里的正确选择<代码>const_cast的功能比必要的功能更强大<代码>静态_cast允许添加cv限定符,因为此转换始终是安全的const_cast
应保留用于实际需要删除cv限定符的不安全强制转换的情况。@DirkHolsopple-static_cast
功能强大,因为它允许更改类型。@DirkHolsopple-这是一个循环参数:您坚持它只应用于“不安全”转换,所以它的使用给你留下了这样的印象。它告诉我cv限定符正在被修改。更改是否“安全”是次要的,取决于它们是否正确。如果我想检查正确性,我更希望得到一个提示,即只有cv限定符在更改。@DirkHolsopple-我的观点是,由于大多数使用static\u cast
是更改对象的类型,而不是其cv限定符,使用static\u cast
在执行安全操作(如添加cv-qualifier)时,会引起不值得注意的注意。它是否适用于已经易变的对象(您希望它的易变程度如何)?我建议在return语句和return类型中对T使用remove_volatile。它实际上对volatile对象有效。冗余volatile是合法的,不会引起任何问题。
template<typename T>
inline T volatile &access_once(T &t) {
return static_cast<T volatile &>(t);
}