如何在赋值期间使volatile结构与volatile相似?

时间:2016-10-12 09:35:31

标签: c++ struct volatile

当一个人从非易失性volatile int分配给int时,编译器。当一个人从同一类型的非易失性volatile struct中分配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,其中提到我应该将引用转换为rvalue ,但我不确定哪个引用的引用,以及在此使用哪个转换语法情况下。

main的第2行上的分配与main的第1行完全相同,没有警告或错误的正确咒语是什么?

1 个答案:

答案 0 :(得分:2)

您的初始问题是因为隐式赋值运算符具有签名

Bar& operator=(const Bar& rhs);

...并且volatile对象无法调用。警告是因为您更新的函数返回了一个volatile引用,但该引用从未使用过。海湾合作委员会认为这可能是一个问题。解决此问题的最简单方法是将返回类型更改为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结构时,您无法链接赋值运算符。我断言这不是一个巨大的损失。

最后一边:为什么使用volatile - 它对多线程代码不是很有用(它对内存映射IO很有用)。