返回值的引用操作符



我正在用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有什么好处吗?

提前感谢你们的帮助。

通过返回对许可证的引用,您保存了一个会导致内存分配的复制操作。通过使其成为const引用,可以防止调用者修改内部状态。

它用于在返回对象时避免不必要的复制,尽管它也取决于调用站点,因为在调用站点可以进行复制,也可以不进行复制:

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<<重载)。

当您有const string &getLicense() const {return license;}时,这意味着您通过引用返回许可值。没有&,您将按值返回。引用:

通过引用返回变量时,将对该变量的引用传递给调用者。然后调用者可以使用此引用继续修改变量,这有时很有用。引用返回也很快,这在返回结构体和类时很有用。

现在,没有const,调用者将能够修改license成员值的值,根据代码,您不希望发生这种情况。

所以,总的来说,使用&是为了按引用返回,这比按值返回快(因为你只返回一个引用,你不复制一个对象),使用const是为了禁止修改。

你可以在c++ -FAQ-lite上阅读更多关于引用返回的信息。

请格式化您的代码!这是不必要的难以解析:

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()所做的)。

通常这是一个效率选项。也就是说,你可以通过value (copy)返回license,但是你复制了license的内容。通过这种方式,您只需授予直接访问权限,但规定它是只读的。

返回值上的

const表示它是只读性质。Const在方法声明的末尾意味着你在声明这个方法不会改变这个对象的值。

如果调用者有Vehicle的const实例,后者尤其重要。调用方不允许调用非const方法,因为它们对自己的Vehicle实例只有只读访问权限。

返回引用可以避免复制,正如其他人已经指出的那样。然而,我觉得有必要指出,故事通常不止于此。

首先,返回对局部对象的引用通常会导致问题。因此,当您返回一个引用时,通常需要做以下两件事之一:

  1. 你正在返回对某个预先存在的对象的引用(例如,许多iostreams操作符被传递给iostream的引用,并返回对同一个iostream的引用;类似地,赋值操作符通常将return *this;)。
  2. 函数动态分配它返回的对象。然而,在这种情况下,返回指针比返回引用更常见。

我甚至可以说,在大多数情况下,所涉及的缺乏复制(或至少从缺乏复制中获得的效率)是一个次要原因,而不是返回引用的主要原因。在iostream的情况下,你返回一个引用主要是因为iostream基本上是一个"身份"类型的对象——也就是说,你不能复制或分配一个。你创建一个,使用对它的引用,唯一的对象,当你完成后,你销毁它。

传递对对象的引用时,主要目的通常是消除副本。但是,当返回引用时,这种情况要少得多。

我还注意到,现在大多数编译器已经实现了返回值优化和命名返回值优化(RVO/NRVO)。这意味着在任何情况下,与返回引用相比,返回值通常不会损失任何效率(实际上,编译器会在内部将返回值的代码转换为接收引用的代码,并直接写入父值)。

底线:返回一个引用并不像最初看起来那么简单或明显。在少数情况下,它是例程(插入、提取和赋值操作符是最明显的),你可能真的需要考虑并知道你在做什么,而不仅仅是一个简单、明显的优化。

最新更新