繁体   English   中英

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

[英]C++: using & operator for pass-by-reference

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

#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的Constructor 2?

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

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

我认为你误解了&运营商在这方面做了什么。 获取变量( &var )的地址不同于表示将参数作为引用传递(就像在const string &a )。

你的代码实际上在做的是隐式创建一个用字符串"bye"初始化的新string对象,然后通过引用传递给Dude构造函数。 也就是说,您的代码基本上是:

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

然后构造函数通过引用接收该字符串对象,并通过复制构造函数将其分配给x

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

两件事情:

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

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

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

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

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

所以以下两行是等价的

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

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

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

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

当你调用Dude("bye") ,编译器会看到这是否是任何构造函数的完美匹配( char[4] )。 不。 然后它检查某些转换( char* )仍然没有。 然后它检查用户转换,并发现可以从char*隐式构造std::string所以它为你创建一个来自char*std::string ,并通过引用Dude的构造函数传递它,复制。 在声明结尾处Dude d2 = Dude("bye"); 临时字符串会自动销毁。 如果我们必须为每个单个函数参数自己进行显式转换,那将会很烦人。

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM