我正在学习C ++中的面向对象编程。我对以下代码有些怀疑:
class Vehicle
{
protected:
string license ; int year ;
public:
Vehicle(const string &myLicense, const int myYear) : license(myLicense), year(myYear){}
const string getDesc() const
{
return license + " from " + stringify(year);
}
const string &getLicense() const {return license;}
const int getYear() const {return year;}
};
将参考运算符(&)用作函数的返回值是什么意思。为什么使用方便?我认为结果完全相同,无论你是否在getlicense函数中使用(&),你都使用相同的内存。
为什么这段代码使用保留字const?我发现它可以使用它。在代码中使用const有什么好处吗?
提前感谢您的帮助。
答案 0 :(得分:2)
通过返回对许可证的引用,您可以保存将导致内存分配的复制操作。通过使其成为const引用,它可以防止调用者修改内部状态。
答案 1 :(得分:2)
它用于在返回对象时避免不必要的复制,虽然它也取决于呼叫站点,因为在呼叫站点可以复制,并且可能不会复制:
std::string copy = veh.getLicence(); //makes a copy
const std::string & notAcopy = veh.getLicence(); //does not make a copy
//and most importantly here
size_t size = veh.getLicense().size(); //doesn't make a copy!
返回引用特别有助于链式函数调用。在链式函数调用中,如果您不想在副本上调用函数,那么您将通过引用返回,以便您可以确保链接函数调用位于上原始的对象,就像上面的第三个例子一样。
有些类的返回类型必须是引用类型(或指针类型),否则它将无效,因为它们的复制构造函数已被禁用声明他们private
。最常用的类是IOStream类,例如std::istream
,std::ostream
以及从它们派生的所有类。在这种情况下,您必须使用std::ostream&
作为函数的返回类型(通常这些函数是operator<<
重载)。
答案 2 :(得分:1)
如果您拥有const string &getLicense() const {return license;}
,则表示您返回许可证值参考。如果没有&
,您将按值返回。 Quoting:
当通过引用返回变量时,对变量的引用将传递回调用者。然后调用者可以使用此引用继续修改变量,这有时很有用。通过引用返回也很快,这在返回结构和类时很有用。
现在,如果没有const
,调用者将能够修改license
成员值的值,并根据您不希望这种情况发生的代码。
因此,总而言之,&
用于通过引用返回,这比按值返回更快(因为您只返回引用而不复制对象),{{1用于禁止修改。
您可以阅读有关按引用返回here, on C++-FAQ-lite的更多信息。
答案 3 :(得分:0)
请更好地格式化您的代码!这是不必要的难以解析:
class Vehicle
{
public:
Vehicle(const string & myLicense, const int myYear)
: license(myLicense)
, year(myYear)
{}
const string getDesc() const
{
return license + " from " + stringify(year);
}
const string & getLicense() const {return license;}
const int getYear() const {return year;}
protected:
// good convention: put details that users shouldn't be paying attention to
// below the public parts that they *should* be paying attention to
string license;
int year;
};
返回const string &
意味着您正在向外界提供只读(const)访问权限,以直接与此对象的许可证进行交互(通过引用)(因为这就是getLicense()所做的事情。)
通常这是一种效率选择。即你可以按价值(复制)返还许可证,但是你要复制许可证的内容。这样你就可以直接访问,但规定它是只读的。
返回的const表示它是只读的性质。 方法声明结束时的const表示您声明此方法不会更改此对象的值。
如果调用者具有Vehicle的const实例,则后者尤为重要。不允许调用者调用非const方法,因为它们只具有对其Vehicle实例的只读访问权。
答案 4 :(得分:0)
返回引用可以避免副本,正如其他人已经指出的那样。然而,我觉得有必要指出,故事通常比这更多。
首先,返回对本地对象的引用通常会导致问题。因此,当您返回引用时,通常需要执行以下两项操作之一:
我甚至可以说,在大多数案例中,所涉及的复制缺乏(或至少是因缺乏复制而获得的效率)比主要版本更多或更为副业你返回参考的原因。在iostream的情况下,你返回一个引用主要是因为iostream基本上是一个“身份”类型的对象 - 即你不能复制或分配一个。你创建一个,使用对那个,唯一对象的引用,当你完成后你将其销毁。
当传递对对象的引用时,主要目的通常是消除副本。但是,当返回引用时,情况就更少了。
我还注意到,很长一段时间以来,大多数编译器都实现了返回值优化和命名返回值优化(RVO / NRVO)。这意味着返回一个值通常不会失去与在任何情况下返回引用相比的任何效率(实际上,编译器会在内部将代码返回一个值转换为接收的代码引用,并直接写入父级的值。)
底线:返回引用并不像最初看起来那么简单或明显。除了常规(插入,提取和赋值运算符最明显)的极少数情况之外,您可能真的需要考虑并知道自己在做什么,而不仅仅是简单明了的优化。