[英]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.