【问题标题】:Pointer to a const object can change the object?指向 const 对象的指针可以改变对象吗?
【发布时间】:2021-08-05 01:46:36
【问题描述】:

指向 const 对象的指针不允许更改对象。例如:

class foo {
    public:
        int m_data;
        
        foo() : m_data{11} {}
};

void change(const foo *obj)
{
    obj -> m_data = 21;   // gives error, normal
}

这是正常的行为。

我不明白的是,当我们添加一个额外的指针变量时,无论是相同类型(如foo *)还是其他类型(如bar *),但不是像@987654326这样的基本类型@,那么我们可以改变指针指向的值(从指针指向 const 类型本身)。

这怎么可能?

class foo {
    public:
        int m_data;
        foo *m_next;
        
        foo() : m_data{11}, m_next{nullptr} {}
};

void change(const foo *obj)
{
    obj -> m_next -> m_data = 21;   // does not give any error! why?
}

如果我们在 foo 中使用其他类型,也会发生这种情况,例如 bar *

为什么会这样?如何定义函数以确保我的函数不能更改对象指向的值?

【问题讨论】:

  • 您没有更改m_next*obj 中的任何其他内容。 fooconst 意味着您不能,例如,重新分配 m_next 以指向其他东西。有关区别的更多信息,请参阅here 或类似问题。
  • constness 不可传递
  • 关于如何制作 deep-const 指针:How to make a deep-const pointer

标签: c++ pointers constants


【解决方案1】:

在您的示例中,foo* m_next 是指向可变 foo 对象的指针成员变量。指针本身被认为是对象实例的一部分,而不是被指向的对象。

通过更改m_next,您正在更改指针,该指针被视为foo 实例的一部分。在change 中执行类似obj->m_next = nullptr; 的操作将是无效的,因为您正在更改作为常量foo 实例一部分的内存。 (注意:不要在实际代码中将随机指针设置为 null,除非您确定它是安全的,或者可能存在内存泄漏)。

通过m_next-> 访问m_next 指向的对象,您正在访问不属于传递给change 的const 实例的另一个对象的内存。这是完全有效的。

你可以说 constness 是不及物的; const 对象不会使通过它(通过指针)访问的对象为 const。

【讨论】:

    【解决方案2】:
    obj -> m_next -> m_data = 21;   // does not give any error! why?
    

    因为这并没有改变对象。此对象的m_next 指针与之前完全相同。

    这只会改变m_next 指向的任何东西。无论如何,这与拥有此 m_next 指针的对象无关。

    现在,另一方面,如果您尝试为 m_next 指针本身分配一些东西,而不是它指向的任何东西,那么您将得到预期的错误。

    对象包含的唯一内容是它的枚举成员。这行代码没有改变它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 2022-01-04
      • 1970-01-01
      • 2010-09-18
      相关资源
      最近更新 更多