gpt4 book ai didi

c++ - 一类的物理常数

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:50:52 27 4
gpt4 key购买 nike

我正在学习Bjarne Stroustrup的“C++编程语言”,他谈论了类的逻辑和物理常数。

逻辑常数的示例如下所示:

class A {
int m;
void func() const { m++; } //forbidden
}

可以通过强制转换来绕开它,例如:
class A {
int m;
void func() const { (A*) this)->m++; } //allowed
}

用他的话说,逻辑常数是

"an object that appears constant to its users."



而物理常数是

"stored in read-only memory"



作为说明,他说

physical constness may be enforced by placement of an object in read-only memory only for classes without constructors



我不太明白这句话。有人可以提供有关如何强制物理常量的解释,如果类具有构造函数,为什么它不起作用?

最佳答案

您已经收到了几个答案,但是我相信其中大多数(如果不是全部)都错了。

为了更好地理解C++中的const情况(并涉及其他答案中提到的概念),我们考虑的不是C++程序中可能遇到的两种,而是三种可能的constness级别。

  • 硬件/操作系统级别的物理常数
  • 语言级别的物理常数
  • 逻辑常数(当然,也是语言级别)

  • 硬件/操作系统级别的物理常数是其他答案似乎正在描述的物理常数。当对象被放置在防止写操作的内存中时,它就会发生:只读(RO)内存。可以通过硬件提供的方法或操作系统提供的方法,或通过这两种方法来实现保护。但是,C++语言本身并未将这种常量性划分为独特的类别。 C++语言本身不涉及此类低级事务。当物理常量性的概念出现在C++上下文中时,通常指的是下一类常量性。

    语言级别的物理常数。仅当您将对象声明为 const时,才会发生这种常数。从C++语言的角度来看,以下对象是物理常数
    const double d = 5;
    const int i = 42;
    const std::string str = "Hello World!";
    const MyClass c;

    请注意,这些对象是否真的放在RO内存中并不重要。该语言说,任何修改这些对象的尝试都会导致未定义行为(UB),无论内存是否为RO。另请注意,如果您尝试修改这些对象,则该UB的表现不仅限于程序崩溃(如果它们确实在RO内存中)。例如,编译器可以自由地假设这些对象永不更改,并且可以在该假设下优化代码,从而在似乎不必要的情况下消除对这些对象的访问。因此,即使这些对象占用的内存是可写的,即使您设法以某种方式“成功”修改了它们,您的代码仍可能会表现得好像从未进行过修改。 UB是UB。什么都可能发生。

    从语言的角度来看,这种常数当然旨在包括第一种。

    最后,到 逻辑常数。 C++中的逻辑常数是所谓的对象访问路径的常数。访问路径是允许您间接访问现有对象的引用或指针。考虑这个声明
    const MyClass* pc;

    这是 const MyClass类型的指针。但是请注意:这实际上并不意味着该指针指向的实际对象是一个常数。它只是让您“将其视为”常量。该对象可以很容易地是一个常数
    const MyClass c;
    pc = &c;

    或可能是非恒定的
    MyClass nc;
    pc = &nc;

    换句话说,只有该指针 p,您就有到 MyClass类型的某个对象的恒定accss路径。您不知道并且(通常)不需要知道该对象是否真的是一个常数。由于提供给您的访问路径是常量,因此您必须将该对象视为常量。当然,如果您以某种方式知道该访问路径另一端的对象不是常量,则可以合法地丢弃该访问路径的常数。
    MyClass* p = const_cast<MyClass*>(pc);

    并在对象上执行修改操作(当然,在一般情况下,这不是一种好的编程习惯,但是有其有效的用法)。如果路径另一端的对象毕竟是常量,则由于上述原因,该行为将是不确定的。

    请注意,原始帖子中的示例正是在讨论这一点。当您将 A类的方法声明为 const时,它仅意味着传递给该方法的隐式 this参数将具有 const A*类型,即它将为 A对象提供恒定的访问路径。这就是我上面描述的逻辑常数。再次注意,如果将该对象声明为 const A a;,则它是语言级别的物理常数,并且如示例中所示对其进行修改是非法的,无论该对象是否驻留在RO内存中。

    现在,为了提供上述说明的最后一个例子,请考虑以下声明
    const MyClass* const* const* const p = /* whatever */;

    该声明中包含4个 const限定词。这些预选赛中的一个在质量上与其他预选赛有很大不同。它是最右边的一个。最右边的 const声明对象 p的物理常数(指针本身的常数),而其余 const限定符声明它们将指向的对象的逻辑常数(访问路径的常数)。

    再一次,我相信在他的书Stroustrup中,他要谈论的是第二性和第三性概念的区别,而不是第一性,因为C++语言实际上并没有将第一性与第二性区分开。注意,该示例说“允许”通过放弃常量来进行修改,而语言规范明确指出,用这种方法修改第二种常量立即是非法的。

    关于c++ - 一类的物理常数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2352902/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com