我正在观看视频,看到了这段代码:
class Dog {
public:
Dog() : age(3), name("dummy") {}
void setAge(const int &a) { age = a; }
private:
int age;
std::string name;
};
我对setAge
的函数签名感到好奇,因为我从未使用const
作为函数参数。我看了几个相关的答案,但没有一个似乎回答了我的问题。
在这样一个基本的例子中,很难看到将const
引用传递给函数的好处。
您有什么理由想要将参考设为const
吗?我能想到的唯一应用就是在嵌入式编程中制作变量的副本可能会浪费宝贵的空间。
是否有任何简单的例子,通过const
引用可以轻易看到影响?
答案 0 :(得分:5)
制作变量的副本会浪费宝贵的空间并浪费宝贵的时间,这就是为什么避免不必要的副本在任何类型的编程中都要担心,而不仅仅是嵌入式编程。因此,使用const T &
引用传递只读参数一直是C ++中的习惯用法。
然而,它通常被保留用于传递"重"对象,即复制相对昂贵的对象。将它与标量类型一起使用(如在您的示例中)几乎没有任何意义。
答案 1 :(得分:4)
考虑以下三个例子:
(i) void setAge(int &a) { age = a; }
(ii) void setAge(const int &a) { age = a; }
(iii) void setAge(int a) { age = a; }
进一步认为你的类是一个封装的对象,外界通常不知道里面发生了什么。
然后,使用案例(i)
,调用者无法知道之后a
没有被更改。
int a=3;
dog.setAge(a); //case (i): what is "a" afterwards?
在函数调用之后,人们不知道a
保持什么值 - 实际上,函数签名告诉调用者可能发生a
的更改。
另一方面,通过使用变量(ii)
,您再次通过引用传递对象,即您不进行复制,而是告诉函数存储器地址可以去参考的参数。与案例(i)
相反,现在您确保调用者“您的参数不会发生任何事情”。也就是说,您可以安全地使用该参数,并确保它仍具有与之前相同的值( - 至少在原则上,因为函数内部可能会发生诸如const_cast
之类的错误)。
最后,在(iii)
的情况下,一个人复制int
并在函数内部使用它。对于像int
这样的内置类型,这实际上是传递函数参数的首选方式。但是,如果对象的复制费用很高,则可能无效。
关于整个 const正确性 -topic,请参阅here。
答案 2 :(得分:3)
考虑具有大内存占用量的对象。您需要将它传递给一个函数 - 这个函数只会在不改变对象的情况下提取一些信息。在这种情况下,const
引用是一个很好的候选者。
std::vector
可以是一个例子,Matrix对象是另一个例子。
答案 3 :(得分:3)
void setAge(const int &a) { age = a; }
您传递的是const int reference
,您无意修改函数a
内的值setAge
。
void setAge(int &a) { age = a; }
您正在传递int reference
,您并不关心函数setAge
是否修改了函数setAge中的值a
。
这里做const正确性是一种很好的编程实践,可以作为更好的接口定义的实践。第一个函数签名非常清楚地传达了消息,第二个函数签名与第一个相比是模糊的。
您可以在此处阅读有关const正确性的更多信息https://isocpp.org/wiki/faq/const-correctness#overview-const