提问者:小点点

为什么volatile int可以转换为int而volatile T不能转换为T?


请考虑以下代码:

#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类可复制?

注意:欢迎引用C++标准


共2个答案

匿名用户

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

type::type(type const&);

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

[class.copy.ctor]

7类x隐式声明的复制构造函数的形式为

X::X(const X&)

如果类类型M(或其数组)的每个潜在构造的子对象都有一个复制构造函数,其第一个参数为const M&;const volatile M&;类型。 否则,隐式声明的复制构造函数将具有

X::X(X&)

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

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

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

有没有方法使volatile类可复制?

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

匿名用户

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

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

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

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

有没有一种方法可以让一个易失性的类成为可复制的呢?

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

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

根据您期望volatile的行为方式(volatile对象的访问是在实现中定义的),可能不一定有一种方法来实现这个构造函数,而如果存在多个子对象,则可以期望从volatile对象中进行复制。

Volatile类对象通常不太有用,在我看来最好避免使用。