成员函数什么时候应该同时是 const 和 volatile ?

发布于 2024-07-15 09:18:02 字数 562 浏览 8 评论 0原文

我正在阅读有关易失性成员函数的内容,并发现成员函数可以同时是const和易失性的。 我没有得到这样的东西的真正用途。 任何人都可以分享他们将成员函数同时用作 const 和 volatile 的实际使用经验吗?

我编写了小类来测试相同的内容:

class Temp
{
public:

    Temp(int x) : X(x)
    {
    }

    int getX() const volatile
    {
        return X;
    }

    int getBiggerX()
    {
        return X + 10;
    }
private:
    int X;
};

void test( const volatile Temp& aTemp)
{
    int x = aTemp.getX();
}

int main(int argc, char* argv[])
{
    const volatile Temp aTemp(10);
    test(aTemp);

    return 0;
}

I was reading about volatile member function and came across an affirmation that member function can be both const and volatile together. I didn't get the real use of such a thing. Can anyone please share their experience on practical usage of having member function as const and volatile together.

I wrote small class to test the same:

class Temp
{
public:

    Temp(int x) : X(x)
    {
    }

    int getX() const volatile
    {
        return X;
    }

    int getBiggerX()
    {
        return X + 10;
    }
private:
    int X;
};

void test( const volatile Temp& aTemp)
{
    int x = aTemp.getX();
}

int main(int argc, char* argv[])
{
    const volatile Temp aTemp(10);
    test(aTemp);

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

贱人配狗天长地久 2024-07-22 09:18:02

cv 资格提炼意味着:

我不会改变这个值,但有一些东西可以。

您向自己承诺不会更改该值(const 限定),并请求编译器不要对这个对象动手动脚,并关闭所有优化(易失性< /code> 资格)。 不幸的是,在公平对待易失性方面,编译器供应商之间几乎没有标准。 毕竟,易失性是对编译器的提示

一个实际用例是系统时钟。 假设 0xDEADBEEF 是您要写入的硬件时钟寄存器的系统特定地址:

int const volatile *c = reinterpret_cast<int *>(0xDEADBEEF);

您无法修改该寄存器值,但每次读取它时,它可能会有不同的值。

此外,还可以使用它来建模 UART

The cv qualification distilled means:

I won't change the value, but there is something out there that can.

You are making a promise to yourself that you won't change the value (const qualification) and requesting the compiler to keep its slimy hands off of this object and turn off all optimization (volatile qualification). Unfortunately, there is little standard among the compiler vendors when it comes to treating volatile fairly. And volatile is a hint to the compiler after all.

A practical use case of this is a system clock. Supposing 0xDEADBEEF was your system specific address of a hardware clock register you'd write:

int const volatile *c = reinterpret_cast<int *>(0xDEADBEEF);

You can't modify that register value, but each time you read it, it is likely to have a different value.

Also, can use this to model UARTs.

梦境 2024-07-22 09:18:02

您要求提供易失性成员函数的实际示例。 好吧,我想不出一个,因为我能想象的唯一情况是如此低级,以至于我一开始不会考虑使用成员函数,而只是一个带有数据成员的普通结构通过易失性引用访问。

然而,为了回答这个问题,我们在其中放入一个 const 易失性函数。 假设您有一个地址为 0x378h 的端口,其中包含 2 个整数,每个整数 4 个字节。 然后你可以写

struct ints {
    int first;
    int second;
    int getfirst() const volatile {
        return first;
    }

    int getsecond() const volatile {
        return second;
    }
      // note that you could also overload on volatile-ness, just like
      // with const-ness
};

// could also be mapped by the linker. 
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);

你正在陈述

我不会改变它们,但是这个抽象语义之外的另一件事可能会改变它。 因此,始终从其地址进行实际加载。

实际上,易失性表明对象的值可能不是最后存储到其中的值,但实际上是未知的,并且可能已被外部(编译器无法观察到)条件更改。 因此,当您读取易失性对象时,编译器必须模拟精确的抽象语义,并且不执行任何优化:

a = 4;
a *= 2; 
  // can't be optimized to a = 8; if a is volatile because the abstract
  // semantics described by the language contain two assignments and one load.

以下内容已经确定了 易失性 的作用。 一切都可以在标准的 1.9 中找到。 它谈论的参数是实现定义的东西,比如某种类型的 sizeof 。

本国际标准中的语义描述定义了参数化的非确定性抽象机。 本国际标准对符合实施的结构没有提出要求。 特别是,它们不需要复制或模拟抽象机的结构。 相反,需要一致的实现来模拟(仅)抽象机的可观察行为,如下所述。 [...]

执行格式良好的程序的一致实现应产生与具有相同程序和相同输入的抽象机的相应实例的可能执行序列之一相同的可观察行为。 [...]

抽象机的可观察行为是其对易失性数据的读写序列以及对库 I/O 函数的调用。

You asked for a practical example of volatile member functions. Well i can't think of one because the only situations i could imagine are so low-level that i would not consider using a member function in the first place, but just a plain struct with data-members accessed by a volatile reference.

However, let's put a const volatile function into it just for the sake of answering the question. Assume you have a port with address 0x378h that contains 2 integers, 4 bytes each. Then you could write

struct ints {
    int first;
    int second;
    int getfirst() const volatile {
        return first;
    }

    int getsecond() const volatile {
        return second;
    }
      // note that you could also overload on volatile-ness, just like
      // with const-ness
};

// could also be mapped by the linker. 
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);

You are stating

I'm not changing them, but another thing outside this abstract semantics could change it. So always do a real load from its address.

Actually, volatile signals that the value of an object might not be the value last stored into it but is actually unknown and might have been changed in between by external (not observable by the compiler) conditions. So when you read from a volatile object, the compiler has to emulate the exact abstract semantics, and perform no optimizations:

a = 4;
a *= 2; 
  // can't be optimized to a = 8; if a is volatile because the abstract
  // semantics described by the language contain two assignments and one load.

The following already determines what volatile does. Everything can be found in 1.9 of the Standard. The parameters it talks about are implementation defined things, like the sizeof of some type.

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below. [...]

A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible execution sequences of the corresponding instance of the abstract machine with the same program and the same input. [...]

The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

风追烟花雨 2024-07-22 09:18:02

我从来不需要任何东西既是常量又是易失性的,但这是我的猜测:

常量:您,您的代码,不允许更改该值。

易失性:该值可能会随着时间的推移而改变,而您的程序无需执行任何操作。

因此,由另一个进程或某些硬件公开的一些只读数据将是常量且易失的。 它甚至可以内存映射到您的进程中,并将页面标记为只读,因此如果您尝试写入它(如果它不是 const),您将遇到访问冲突。

I've never needed anything being both const and volatile, but here's my guess:

Const: You, your code, is not allowed to change the value.

Volatile: The value may change over time without your program doing anything.

So some read-only data exposed by another process or by some hardware would be const and volatile. It could even be memory-mapped into your process and the page marked read-only, so you'd get an access violation if you tried to write to it if it wasn't const.

月朦胧 2024-07-22 09:18:02

我认为我们拥有“const 易失性”函数的原因与我们拥有“受保护”继承的原因相同:语法允许它,所以我们最好为它想出一个含义。

I think that the reason we have "const volatile" functions is the same as the reason we have "protected" inheritance: The grammar allows it , so we had better think up a meaning for it.

梦与时光遇 2024-07-22 09:18:02

我能想到的一种情况可能需要在成员函数上同时使用 const 和 volatile ,那就是在嵌入式系统情况下,您有一个函数在逻辑上是 const 但实际上必须修改共享内存位置中的数据缓存(例如构建一个按需位图并缓存位图,以防很快再次需要相同的位图)。 它当然不会经常出现。

One situation I can think of that could require both const and volatile on a member function would be in an embedded systems situation where you had a the function was logically const but actually had to modify a data cache in a shared memory location (e.g. building a bitmap on demand and caching the bitmap in case the same bitmap was needed again soon). It certainly does not come up very often.

断肠人 2024-07-22 09:18:02

标记为 const 易失性的对象将不允许被声明它的代码更改。 由于 const 限定符,将引发该错误。 限定符的易失性部分意味着编译器无法针对对象优化代码。

在嵌入式系统中,这通常用于访问可由硬件读取和更新的硬件寄存器,因此能够通过代码写入寄存器是没有意义的。 例如,串行端口的状态寄存器。各个位将指示状态,例如字符是否正在等待读取。 每次读取该状态寄存器都可能产生不同的值,具体取决于串行端口硬件中发生的其他情况。 写入状态寄存器是没有意义的,但您需要确保每次读取寄存器都会导致对硬件的实际读取。

下面是一个插图:

//We assume that the below declared pointers
//point to the correct
//hardware addresses
unsigned int const volatile *status_reg;
unsigned char const volatile *recv_reg;

#define CHAR_READ 0x01

int get_next_char()
{
    while((*status_reg & CHAR_READ) == 0);
    return *recv_reg;
}

希望这会有所帮助。

问候
桑迪潘·噶玛卡尔。

An object marked as const volatile will not be allowed to change by the code where it is declared. The error will be raised due to the const qualifier. The volatile part of the qualifier means that the compiler cannot optimize the code with respect to the object.

In an embedded system this is typically used to access hardware registers that can be read and are updated by the hardware, so it makes no sense to be able to write to the register via the code. An example might be the status register of a serial port.Various bits will indicate a status like if a character is waiting to be read. Each read to this status register could result in a different value depending on what else has occurred in the serial port hardware. It makes no sense to write to the status register but you need to make sure that each read of the register results in an actual read of the hardware.

Below is an illustration :

//We assume that the below declared pointers
//point to the correct
//hardware addresses
unsigned int const volatile *status_reg;
unsigned char const volatile *recv_reg;

#define CHAR_READ 0x01

int get_next_char()
{
    while((*status_reg & CHAR_READ) == 0);
    return *recv_reg;
}

Hope this helps.

Regards
Sandipan Karmakar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文