C ++:使用&运算符用于传递引用

时间:2011-11-02 21:51:13

标签: c++ pass-by-reference

我正在自学C ++,在这个过程中我正在编写简单的小程序来学习基本思想。关于“pass-by-reference”,我很困惑为什么下面的代码可以工作(一些代码只是练习重载构造函数):

#include <iostream>
#include <string>
using namespace std;

class Dude
{
public:
  string x;
  Dude();                    // Constructor 1
  Dude(const string &a);     // Constructor 2
};

Dude::Dude() : x("hi") {}
Dude::Dude(const string &a) : x(a) {}

int main()
{
  Dude d1;
  Dude d2 = Dude("bye");

  cout << d1.x << endl;
  cout << d2.x << endl;

  return 0;
}

在“main()”中,我创建一个“Dude”类型的对象“d2”,并使用构造函数2将“x”设置为字符串“bye”。

但是在构造函数2的声明中,我告诉它接受字符串的地址,而不是字符串本身。那么为什么我可以传递它“bye”(这是一个字符串)。为什么我不必创建变量字符串,然后将该字符串的地址传递给Dude的构造函数2?

9 个答案:

答案 0 :(得分:5)

这实际上说明了C ++最酷和最有用的功能之一:临时变量。由于您指定了字符串引用为const,因此编译器允许您将对临时值的引用传递给该函数。所以,这是Dude d2 = Dude("bye");幕后发生的事情:

  • 编译器确定要使用的最佳构造函数是Dude::Dude(const string &)。如何做出这个选择是一个完全不同的主题。
  • 但是,为了使用该构造函数,您需要string值。现在,"bye"const char[4],但编译器可以将其简单地转换为const char *可以将转换为string。因此,创建了一个匿名临时变量(称为temp1)。
  • 使用string::string(const char *)调用
  • "bye",结果存储在temp1
  • 中 使用对Dude::Dude(const string&)的引用调用
  • temp1。结果被分配给d2(实际上,它被分配给另一个临时变量,Dude的复制构造函数被调用,其中包含对它的const引用,分配给 d2。但在这种情况下结果是一样的。)
  • temp1被丢弃。这是字符串析构函数string::~string()temp1
  • 上运行的地方
  • 控制传递到下一个语句

答案 1 :(得分:2)

我认为你误解了&运算符在这种情况下的作用。获取变量(&var)的地址不同于表示参数将作为引用传递(正如您在const string &a中那样)。

您的代码实际执行的操作是隐式创建使用字符串string初始化的新"bye"对象,然后将该对象通过引用传递给{{> 1}}构造函数。也就是说,您的代码基本上是:

Dude

然后构造函数通过引用接收该字符串对象,并通过复制构造函数将其分配给Dude d2 = Dude(string("bye"));

答案 2 :(得分:2)

在这种情况下,string有一个构造函数,它接受const char*并且未声明explicit,因此编译器将创建一个临时string(使用{{创建) 1}},前面提到的构造函数)然后你的string("bye")被设置为引用那个临时的。

答案 3 :(得分:1)

两件事:

1)代码中没有“地址”这样的东西。 const string&表示“常量引用string”。

您可能会对这样一个事实感到困惑:符号&也在完全不同的上下文中用作创建指针的“address-of”运算符:T x; T * p = &x;。但这与参考文献无关。

2)您实际上并不一定要使用您声称为d2的构造函数;相反,您正在使用构造函数#2创建一个临时对象,然后通过临时的复制构造函数构造d2。直接构造为Dude d2("bye");

答案 4 :(得分:1)

当您使用字符串参数调用第二个构造函数时,将创建一个引用该字符串副本的临时变量并将其传递给构造函数。

答案 5 :(得分:1)

构造函数2没有将地址写入字符串,const string& a表示对std::string对象的常量引用。您可以将构造函数传递给字符串文字的原因是因为std::string类包含一个带有const char *的非显式构造函数。因此,在调用Constructor 2之前,编译器会先隐式将您的字符串文字转换为std::string

所以以下两行是等价的

Dude d2 = Dude("bye");
Dude d2 = Dude( std::string("bye") );

此外,在编写构造函数时,更喜欢在初始化列表中而不是在构造函数体内初始化成员变量

Dude(const string &a) : x(a) {}

答案 6 :(得分:1)

temporaries可以绑定到const引用,可能是出于这个原因。

当您调用Dude("bye")时,编译器会查看是否与任何构造函数完全匹配(char[4])。不。然后它会检查某些转化(char*)仍然不成功。然后它会检查用户转化,并发现可以std::string隐式构建char*,因此它会为您std::string创建一个char*,并通过引用传递给它Dude的构造函数,它制作副本。在语句Dude d2 = Dude("bye");的末尾,临时字符串将自动销毁。如果我们必须为每个函数参数自己进行显式转换,那将会很烦人。

传递给引用参数的变量将自动传递其地址。这很好,因为它允许我们处理具有值语义的对象。我不必考虑将它传递给字符串的实例,我可以传递 "bye"

答案 7 :(得分:1)

构造函数#2接受对const string的引用。这允许它接受对预先存在的对象的临时对象的引用(没有const限定符,不接受对临时对象的引用。)

std::string有一个构造函数,它接受一个指向char的指针。编译器使用它来创建一个临时的std::string对象,然后将对该临时文件的引用传递给你的ctor。

请注意,编译器只会(隐式)为您执行一个转换。如果您需要多次转换才能从源数据获取目标类型,则需要明确指定其中一个转换。

答案 8 :(得分:1)

而“&amp;”是一个addressof运算符,当作为方法定义/声明的一部分声明时,它意味着引用被传递给方法。在这种情况下的参考是d2。注意,D2不是指针,它是一个引用。在构造函数中,“a”表示内容为“hi”的字符串对象。这是C ++中方法的引用传递的典型示例。