【问题标题】:Why is volatile int convertible to int but volatile T is not convertible to T?为什么 volatile int 可以转换为 int 而 volatile T 不能转换为 T?
【发布时间】:2020-07-03 14:04:25
【问题描述】:

考虑以下代码:

#include <iostream>
#include <type_traits>

struct type {};

int main(int argc, char* argv[]) {
    std::cout << std::is_convertible_v<volatile int, int> << " ";
    std::cout << std::is_convertible_v<volatile int, volatile int> << " ";
    std::cout << std::is_convertible_v<volatile type, type> << " ";
    std::cout << std::is_convertible_v<volatile type, volatile type> << std::endl;
    return 0;
}

打印出来

1 1 0 0

为什么volatile int 可以转换为int,而volatile type 不能转换为type?为什么volatile type 甚至不能转换为volatile type

有没有办法让volatile 类可复制?

注意:欢迎参考 C++ 标准

【问题讨论】:

    标签: c++ type-conversion language-lawyer volatile


    【解决方案1】:

    type 的隐式声明的默认构造函数具有此签名

    type::type(type const&);
    

    引用不能绑定到 volatile 对象,因为那样会丢弃限定符。

    [class.copy.ctor]

    7 X 类的隐式声明的复制构造函数将 有表格

    X::X(const X&)
    

    如果每个可能构造的类类型 M(或数组)的子对象 其中)有一个复制构造函数,其第一个参数是类型 const M&amp;const volatile M&amp;。否则,隐式声明 复制构造函数的形式为

    X::X(X&)
    

    无论哪种方式,编译器都不会隐式声明一个构造函数,该构造函数接受对 volatile 对象的引用。

    转换中的目标对象也是易失的这一事实也没有什么区别。这种转换需要能够绑定到 volatile 源的复制构造函数。

    构造函数不会复制基本类型,因此这种行为不会限制它们。

    有没有办法让volatile 类可复制?

    如果需要,您需要用户声明的复制构造函数,该构造函数通过对 const volatile 对象的引用来接受。

    【讨论】:

    • Nitpick:您可以拥有一个通过引用可变volatile接受的复制构造函数,但不应该
    【解决方案2】:

    这种到相同类型的转换(忽略限定符)是复制/移动。

    type 有一个隐式生成的复制和移动构造函数,它接受对非易失性对象的引用。此类引用不能绑定到 volatile 参数,因此不允许从 volatile 转换。

    没有隐式生成的构造函数接受对 volatile 限定对象的引用。 (同样,没有隐式的 volatile 限定赋值运算符,也没有带有 volatile 限定参数的赋值运算符)。

    这是 C++ 与允许复制 volatile 结构的有效 C 不兼容的一种方式。

    有没有办法让 volatile 类可复制?

    您可以在技术上定义允许它的构造函数:

    struct type {
        type()                       = default;
        type(type          const & ) = default;
        type(type                &&) = default;
        type(type volatile const & ) {}
        type(type volatile       &&) {}
    };
    

    根据您期望 volatile 的行为方式(对 volatile 对象的访问是由实现定义的),可能不一定有一种方法可以以您期望从 volatile 对象复制的方式来实现此构造函数,如果有多个子对象的话.

    Volatile 类对象通常不是很有用,我认为最好避免使用。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2013-09-22
    • 2010-11-27
    相关资源
    最近更新 更多