【问题标题】:Const references sometimes lead to confusionconst 引用有时会导致混淆
【发布时间】:2014-07-29 14:00:44
【问题描述】:

我是 C++ 新手。我了解到应尽可能使用引用,并且仅在绝对必要时才应使用指针。我还了解到,当函数不改变引用变量时,应该在函数参数中使用const引用。

我理解其中的原因并同意他们的观点,但有一种常见情况是 const 引用会导致混淆,即可变对象“变得不可变”作为声明 const 引用的效果(常量)到一个对象。例如,Foo 类有一个名为incrementX() 的方法,它在调用时会改变Foo 的状态:

class Foo {
    public:
        void incrementX();
    private:
        private int x;
}
void Foo::incrementX() {
    x++;
}
class Bar {
    public:
        void doSomethingWith(const Foo &foo);
}
void Bar::doSomethingWith(const Foo &foo) {
    foo.incrementX(); // <- illegal because incrementX() is not a const method
}
int main() {
    Foo foo;
    Bar bar;
    bar.doSomethingWith(foo);
}

通常的解决方案是将incrementX() 声明为const 方法,这反过来又迫使我将变量x 声明为mutable 变量。问题是,通过将incrementX() 转换为const 方法,我是说这个方法不应该改变对象的状态,这在上面的例子中是不正确的。不仅不正确,而且该方法的意图也是改变对象的状态。

我很好奇有经验的 C++ 程序员如何处理这种情况。在这种情况下,我倾向于使用 const 指针 (Foo * const foo),是否会推荐/不鼓励这样做?

谢谢。

编辑:为了澄清我困惑的原因,我经常听到人们说“当函数承诺不更改参数时使用 const refs”,但是什么究竟“改变参数”是什么意思?这是否意味着该函数承诺不会将新对象分配给参数,或者是否意味着它不会改变对象的状态?当然,const 引用不允许这两种更改,但是 const 引用的主要问题是什么? 是它不会为参数分配新值,还是它不会改变const 引用所引用的对象的状态吗?

【问题讨论】:

  • 如果您需要调用者恢复修改,请使用非常量引用。如果不是,则按值传递。
  • 如果函数要修改它的参数,那么参数不应该是const
  • 修改其参数是什么意思?是用另一个Foo实例替换foo还是改变foo的状态
  • @le_ninja_sloth:表示修改其任意非mutable成员,或调用任意非const成员函数。 (C++ 中没有“替换对象”的概念;我假设您的意思是“用另一个值赋值”,这是通过调用非const 赋值运算符来完成的。)
  • @MikeSeymour 这正是我所说的“替换对象”的意思,抱歉我选错了词。好的,现在我明白了。当我听到人们说“当你的函数承诺不更改参数时使用 const refs” 我认为他们的意思是函数承诺不会为参数分配新值。

标签: c++ pointers reference constants


【解决方案1】:

通过const Foo &amp;

void Bar::doSomethingWith(const Foo &foo)

承诺不修改foo。因此它可能不会将其称为非常量 incrementX 方法。

如果您有需要调用foo.incrementXBar::doSomethingWith(Foo &amp;foo)(因此需要采用它的参数非常量引用),那么您应该重新考虑是否真的适合成为Bar 的方法而不是@首先是987654328@。

【讨论】:

  • 好的,我想我明白了。当我听到人们说当你的函数承诺不更改相关参数时使用 const refs 我(错误地)认为主要前提是函数承诺不会为参数分配新值,像这样:foo = Foo().
  • @le_ninja_sloth 在 C++ 中有多种方法可以修改参数。您的incrementX 函数修改了对象的x 成员变量,从而修改了对象本身。
  • @le_ninja_sloth:请记住,foo = Foo()foo.operator=(Foo()) 的简写。因为引用是值的别名,而对值的赋值只是对其特殊方法赋值运算符的调用。
【解决方案2】:

如果您希望您的对象会被更改,或者重载函数以使您拥有doSomethingWith(const Foo&amp;)doSomethingWith(Foo&amp;),请不要通过 const 引用。

整个想法是通过const 引用强制const 行为,因此您只能调用标记为const 的成员函数,从长远来看这会减少问题。

PS:我让doSomething 成为Foo 的成员。

例子:

#include <iostream>
using namespace std;

class Foo
{
    int m=0;
public:
    void doSomething(const Foo& foo) const
    {
        cout << "calling const reference" << endl;

    }

    void doSomething(Foo& foo)
    {
        cout << "calling reference" << endl;
        foo.m++;
    }

};


int main()
{
    const Foo f,g ;
    f.doSomething(g); // calls const reference

    Foo h,k;
    h.doSomething(k); // calls reference
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-29
    • 2010-09-23
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-24
    • 1970-01-01
    相关资源
    最近更新 更多