允许函数更改 const 对象的成员变量

Allowing a function to mutate a const object's member variable

提问人:user5965026 提问时间:1/26/2022 最后编辑:Ranoiaetepuser5965026 更新时间:1/26/2022 访问量:708

问:

这与我之前提出的(当前)封闭式问题有关:当自定义类型的对象声明为常量时,是否可以对其进行更改?

假设我们有一个如下所示的东西:

class test 
{
public:
  test() : i{4}, ptr{&i} {};
  int i;
  int *ptr;
  int *get_ptr() const {return ptr;}
};

void func(const test &t, int j) {
  *(t.get_ptr()) = j;
  // auto ptr = t.get_ptr();
  // *ptr = j;
}


int main(int argc, char const *argv[])
{
  test t;
  std::cout << t.i << std::endl;
  func(t, 5);
  std::cout << t.i << std::endl;
}

我们有这个,它需要一个.当我看到这个签名时(如果我没有看函数的实现),它让我想假设里面的任何内容都不会被修改;但是,成员变量可以通过成员变量进行修改,正如我们在这里看到的。funcconst test &tiptr

我通常不会编写以这种方式工作的代码,所以我想知道是否不鼓励这样的代码?

此外,假设(大多数时候)声明为不会发生突变的对象是否合理?const

C++(英语:C++) 常数 不变性 可变

评论

3赞 Drew Dormann 1/26/2022
这是 C++ 允许您搬起石头砸自己的脚的一个很好的例子。 在施工过程中可以指向内部,因为对象只有在施工后才会成为。脚枪锁定并上膛。int *ptrintconstconst
1赞 Adrian Mole 1/26/2022
你在作弊:你没有直接修改传递的对象(例如,尝试更改成员指向的内容)。它指向另一个成员变量的事实是编译器不会检查的。ptr

答:

3赞 littleadv 1/26/2022 #1

关键在这里:

  int *get_ptr() const {return ptr;}

你定义为类似于说“get_ptr不会改变类的任何属性”。事实并非如此。它返回属性的,即 ,并指向 an 的可变实例,而该实例恰好也是类的一个属性。get_ptrconstptrint*int

编译器无法知道这一点,因此从编译器的角度来看,承诺得到了遵守。但是,实际上,您正在规避限定符并允许更改原本不可变的属性。const

这不是最好的编码实践,但显然,编写此类代码的人不应该期望在类方法中保持原样(如果曾经调用过)。iget_ptr

4赞 Joe 1/26/2022 #2

是的,绝对不鼓励这样的代码。它完全忽略了我们首先拥有 const 关键字的原因。该函数正在故意修改它正在宣传的东西,它不会修改

这意味着编写函数的人搞砸了,因为他们声明了它 const,但让它返回一个指向非常量对象的指针(所以可以更改一个,违背了声明函数的目的get_ptr()const)

如果这样的函数可以正确地修改任何返回,那么它应该是一个实现细节,一个用关键字标记的私有(或受保护)变量。get_ptr()mutable

test::get_ptr()应该有两个重载。

const int* get_ptr() const { return ptr; }
int*       get_ptr()       { return ptr; }

如果想要更改给定给它的对象,那么它应该采取 ,而不是func()testtest&const test&

评论

0赞 Joe 1/26/2022
哎呀,你是对的。我的眼睛被遮住了。以为他们正在更改指针,而不是指向的值。固定