将 const 引用传递给函数

Passing const references to functions

我在看视频看到这段代码:

class Dog {
    public:
        Dog() : age(3), name("dummy") {} 
        void setAge(const int &a) { age = a; } 
    private:
        int age;
        std::string name;
};

我对 setAge 的函数签名很好奇,因为我从未将 const 用作函数参数。我查看了几个相关的答案,但 none 似乎回答了我的问题。

在这样一个基本示例中,很难看出将 const 引用传递给函数的好处。

您是否有任何理由想要将 参考文献 设为 const?我能想到的唯一应用是在嵌入式编程中,当复制变量时可能会浪费宝贵的 space.

是否有任何简单的例子,也许可以很容易地看出传递 const 引用的影响?

考虑一个占用大量内存的对象。您需要将它传递给一个函数——一个只会提取一些信息而不会以任何可能的方式更改对象的函数。在这种情况下,const 参考是一个很好的选择。

std::vector可以是一个例子,Matrix对象是另一个例子。

void setAge(const int &a) { age = a; }

您正在传递 const int reference,您不打算修改函数 setAge 内的值 a

void setAge(int &a) { age = a; }

您正在传递一个 int reference,您不关心函数 setAge 是否修改函数 setAge 中的值 a

做 const 的正确性是一个很好的编程实践,作为更好的接口定义的实践。第一个函数签名传达的信息非常清楚,第二个与第一个相比比较模糊。

您可以在此处阅读有关 const 正确性的更多信息 https://isocpp.org/wiki/faq/const-correctness#overview-const

复制变量会浪费宝贵的space并浪费宝贵的时间,这就是为什么在任何编程中都需要担心避免不必要的复制,不只是嵌入式的。因此,使用 const T & 引用来传递只读参数一直是 C++ 中的惯用语。

但是,它通常保留用于传入 "heavy" 对象,即复制成本相对较高的对象。将它与标量类型一起使用(如您的示例)几乎没有意义。

考虑以下三个示例:

(i)   void setAge(int &a) { age = a; }
(ii)  void setAge(const int &a) { age = a; } 
(iii) void setAge(int a) { age = a; } 

进一步把你的class想象成一个封装对象,也就是外面的世界一般不知道里面发生了什么。

然后,使用案例(i),调用者无法知道a之后没有被改变。

int a=3;
dog.setAge(a);  //case (i): what is "a" afterwards?

我们不知道函数调用后 a 的值是什么 -- 事实上,函数签名告诉调用者可能会发生 a 的更改。

另一方面,通过使用变体(ii),您再次通过引用传递对象,即您不进行复制,而是告诉函数它可以访问的内存地址范围。与案例 (i) 相反,现在您确保调用者 "nothing is going to happen to your parameter"。也就是说,您之后可以安全地使用该参数,并确保它仍然具有与以前相同的值(——至少在原则上,函数内部也可能发生像 const_cast 这样的坏事)。

最后,在 (iii) 的情况下,复制 int 并在函数内部使用它。对于像 int 这样的内置类型,这实际上是传递函数参数的首选方式。但是,如果对象的复制成本很高,它可能无效。

关于整个 const 正确性-主题,请参阅 here