如何使 volatile 结构在赋值期间表现得与 volatile int 完全一样?
How can I make a volatile struct behave exactly like a volatile int during assignment?
当一个人从非易失性 int
分配给 volatile int
时,编译器。当从相同类型的非易失性 struct
中分配 volatile struct
时,编译器似乎非常不高兴。
考虑以下简单程序。
struct Bar {
int a;
};
volatile int foo;
int foo2;
volatile Bar bar;
Bar bar2;
int main(){
foo = foo2;
bar = bar2;
}
当我尝试编译这段代码时,我在 main 的第二行出现错误,但第一行没有。
g++ Main.cc -o Main
Main.cc: In function ‘int main()’:
Main.cc:13:9: error: passing ‘volatile Bar’ as ‘this’ argument discards qualifiers [-fpermissive]
bar = bar2;
^
Main.cc:1:8: note: in call to ‘Bar& Bar::operator=(const Bar&)’
struct Bar {
问题似乎是因为 volatile Bar
被传递到赋值运算符的左侧,尽管我不确定为什么这对 int
不是问题。
我查看了 this answer,其中提出了以下修复建议。
struct Bar {
int a;
volatile Bar& operator= (const Bar& other) volatile {
*this = other;
}
};
不幸的是,这导致了以下两个警告。
g++ Main.cc -o Main
Main.cc: In member function ‘volatile Bar& Bar::operator=(const Bar&) volatile’:
Main.cc:4:21: warning: implicit dereference will not access object of type ‘volatile Bar’ in statement
*this = other;
^
Main.cc: In function ‘int main()’:
Main.cc:16:15: warning: implicit dereference will not access object of type ‘volatile Bar’ in statement
bar = bar2;
然后我查看了 this answer,其中提到我应该 将引用转换为右值 ,但我不确定要转换哪个引用,以及转换哪个引用在这种情况下使用的语法。
使 main
第 2 行的赋值与 main
第 1 行的行为完全一样,没有警告或错误的正确咒语是什么?
你最初的问题是因为隐式赋值运算符有签名
Bar& operator=(const Bar& rhs);
... 这对于 volatile
对象是不可调用的。这些警告是因为您更新的函数 return 是一个易失性引用,但该引用从未被使用过。 GCC 认为这可能是个问题。解决此问题的最简单方法是将 return 类型更改为 void!
还有一个问题:你的函数会在无限递归中调用自己。我建议如下:
struct Bar {
int a;
Bar& operator=(const Bar&rhs) = default;
void operator=(const volatile Bar& rhs) volatile // Note void return.
{
// Caution: This const_cast removes the volatile from
// the reference. This may lose the point of the original
// volatile qualification.
//
// If this is a problem, use "a = rhs.a;" instead - but this
// obviously doesn't generalize so well.
const_cast<Bar&>(*this) = const_cast<const Bar&>(rhs);
}
};
volatile Bar vbar;
Bar bar;
int main(){
vbar = bar; // All four combinations work.
bar = vbar;
vbar = vbar;
bar = bar;
return 0;
}
这意味着您将无法在使用可变结构时链接赋值运算符。我断言这不是一个巨大的损失。
最后:你为什么要使用 volatile
- 它对多线程代码不是很有用(它对内存映射 IO 很有用)。
当一个人从非易失性 int
分配给 volatile int
时,编译器。当从相同类型的非易失性 struct
中分配 volatile struct
时,编译器似乎非常不高兴。
考虑以下简单程序。
struct Bar {
int a;
};
volatile int foo;
int foo2;
volatile Bar bar;
Bar bar2;
int main(){
foo = foo2;
bar = bar2;
}
当我尝试编译这段代码时,我在 main 的第二行出现错误,但第一行没有。
g++ Main.cc -o Main
Main.cc: In function ‘int main()’:
Main.cc:13:9: error: passing ‘volatile Bar’ as ‘this’ argument discards qualifiers [-fpermissive]
bar = bar2;
^
Main.cc:1:8: note: in call to ‘Bar& Bar::operator=(const Bar&)’
struct Bar {
问题似乎是因为 volatile Bar
被传递到赋值运算符的左侧,尽管我不确定为什么这对 int
不是问题。
我查看了 this answer,其中提出了以下修复建议。
struct Bar {
int a;
volatile Bar& operator= (const Bar& other) volatile {
*this = other;
}
};
不幸的是,这导致了以下两个警告。
g++ Main.cc -o Main
Main.cc: In member function ‘volatile Bar& Bar::operator=(const Bar&) volatile’:
Main.cc:4:21: warning: implicit dereference will not access object of type ‘volatile Bar’ in statement
*this = other;
^
Main.cc: In function ‘int main()’:
Main.cc:16:15: warning: implicit dereference will not access object of type ‘volatile Bar’ in statement
bar = bar2;
然后我查看了 this answer,其中提到我应该 将引用转换为右值 ,但我不确定要转换哪个引用,以及转换哪个引用在这种情况下使用的语法。
使 main
第 2 行的赋值与 main
第 1 行的行为完全一样,没有警告或错误的正确咒语是什么?
你最初的问题是因为隐式赋值运算符有签名
Bar& operator=(const Bar& rhs);
... 这对于 volatile
对象是不可调用的。这些警告是因为您更新的函数 return 是一个易失性引用,但该引用从未被使用过。 GCC 认为这可能是个问题。解决此问题的最简单方法是将 return 类型更改为 void!
还有一个问题:你的函数会在无限递归中调用自己。我建议如下:
struct Bar {
int a;
Bar& operator=(const Bar&rhs) = default;
void operator=(const volatile Bar& rhs) volatile // Note void return.
{
// Caution: This const_cast removes the volatile from
// the reference. This may lose the point of the original
// volatile qualification.
//
// If this is a problem, use "a = rhs.a;" instead - but this
// obviously doesn't generalize so well.
const_cast<Bar&>(*this) = const_cast<const Bar&>(rhs);
}
};
volatile Bar vbar;
Bar bar;
int main(){
vbar = bar; // All four combinations work.
bar = vbar;
vbar = vbar;
bar = bar;
return 0;
}
这意味着您将无法在使用可变结构时链接赋值运算符。我断言这不是一个巨大的损失。
最后:你为什么要使用 volatile
- 它对多线程代码不是很有用(它对内存映射 IO 很有用)。