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

发布于 2024-12-13 12:21:21 字数 706 浏览 0 评论 0原文

我正在自学 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()”中,我创建了一个对象“d2”类型为“Dude”,并使用构造函数 2 将“x”设置为字符串“bye”。

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

I'm teaching myself C++, and in the process I'm writing simple little programs to learn basic ideas. With respect to "pass-by-reference", I'm confused why the following piece of code works (some of the code is just there to practice overloading constructors):

#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;
}

In "main()", I create an object "d2" of type "Dude", and use Constructor 2 to set "x" to be the string "bye".

But in Constructor 2's declaration, I told it to accept an address of a string, not a string itself. So why can I pass it "bye" (which is a string). Why don't I have to create a variable string, and then pass the address of that string to Constructor 2 of Dude?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

你的呼吸 2024-12-20 12:21:21

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

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

This actually illustrates one of the coolest and most useful features of C++: Temporary variables. Since you specified that the string reference is const, the compiler allows you to pass a reference to a temporary value to that function. So, here's what's happening behind the scenes with Dude d2 = Dude("bye");:

  • The compiler determines that the best constructor to use is Dude::Dude(const string &). How this choice is made is a whole different topic.
  • However, in order to use that constructor you need a string value. Now, "bye" is a const char[4], but the compiler can trivially convert that to a const char *, and that can be turned into a string. So, an anonymous temporary variable (call it temp1) is created.
  • string::string(const char *) is invoked with "bye", and the result is stored in temp1
  • Dude::Dude(const string&) is invoked with a reference to temp1. The result is assigned to d2 (actually, it is assigned to another temporary variable and the copy constructor for Dude is invoked with a const reference to it and that is assigned to d2. But in this case the result is the same.)
  • temp1 is discarded. This is where the string destructor string::~string() is run on temp1
  • Control passes to the next statement
灯角 2024-12-20 12:21:21

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

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

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

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

I think you're misunderstanding what the & operator does in this context. Taking the address of a variable (&var) is different from signifying that a parameter is to be passed as a reference (as you have, in const string &a).

What your code is actually doing is implicitly creating a new string object that's initialized with the string "bye", and then that object is passed by reference to the Dude constructor. That is, your code is essentially:

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

and then the constructor receives that string object by reference and assigns it to x via a copy constructor.

七禾 2024-12-20 12:21:21

在本例中,string 有一个构造函数,该构造函数采用 const char* 并且未声明显式,因此编译器将创建一个临时>string (使用上述构造函数 string("bye") 创建),然后将您的 const string& 设置为引用该临时值。

In this case, string has a constructor which takes a const char* and is not declared explicit, so the compiler will create a temporary string (created with string("bye"), the aforementioned constructor) and then your const string& is set to refer to that temporary.

只有一腔孤勇 2024-12-20 12:21:21

有两件事:

1)代码中没有“地址”之类的东西。 const string& 表示“对字符串的常量引用”。

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

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

Two things:

1) There's no such thing as an "address" in your code. const string& means "constant reference to a string".

You're possibly confused by the fact that the symbol & is also used in an entirely different context as the "address-of" operator to create a pointer: T x; T * p = &x;. But that has nothing to do with references.

2) You're not actually necessarily using the constructor that you claim for d2; rather, you're creating a temporary object with your constructor #2, and then you construct d2 via the copy constructor from the temporary. The direct construction reads Dude d2("bye");.

原来是傀儡 2024-12-20 12:21:21

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

When you call second constructor with a string argument, a temporary variable which references a copy of the string will be created and passed to the constructor.

守不住的情 2024-12-20 12:21:21

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

因此,以下 2 行是等效的。

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

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

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

Constructor 2 is not taking an address to a string, const string& a means a constant reference to an std::string object. The reason why you can pass the constructor a string literal is because the std::string class contains a non-explicit constructor that takes a const char *. So the compiler implicitly converts your string literal to an std::string first before calling Constructor 2.

So the following 2 lines are equivalent

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

Also, when writing constructors, prefer initializing member variables in the initializer list instead of within the body of the constructor

Dude(const string &a) : x(a) {}
悟红尘 2024-12-20 12:21:21

可能出于这个原因,临时变量可以绑定到 const 引用。

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

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

temporaries can be bound to a const reference, probably for this reason.

When you call Dude("bye"), the compiler sees if that is a perfect match (char[4]) for any constructors. Nope. Then it checks certain conversions (char*) still nope. Then it checks user conversions, and finds that std::string can be implicitly constructed from a char* So it creates a std::string from the char* for you, and passes it by reference to Dude's constructor, which makes a copy. At the end of the statement Dude d2 = Dude("bye"); the temporary string is automatically destroyed. It would be irritating if we had to do the explicit casts ourselves for every single function parameter.

Variables passed to a reference parameter will automatically pass their address instead. This is nice, because it allows us to treat objects with value semantics. I don't have to think about passing it an instance of a string, I can pass it the value "bye".

哑剧 2024-12-20 12:21:21

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

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

请注意,编译器只会(隐式)为您执行一次这样的转换。如果您需要多次转换才能从源数据转换为目标类型,则需要显式指定除其中一种转换之外的所有转换。

Constructor #2 accepts a reference to a const string. That allows it to accept a reference to either a pre-existing object or a temporary object (without the const qualifier, a reference to a temporary would not be accepted).

std::string has a constructor that accepts a pointer to char. The compiler is using that to create a temporary std::string object, and then passing a reference to that temporary to your ctor.

Note that the compiler will only (implicitly) do one conversion like this for you. If you need more than one conversion to get from the source data to the target type, you'll need to specify all but one of those conversions explicitly.

待天淡蓝洁白时 2024-12-20 12:21:21

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

While "&" is an addressof operator, when declared in as part of method definition/declaration, it means that the reference is passed to the method. The reference in this case is d2. Note that D2 is not a pointer, it is a reference. In the constructor, "a" represents the string object with contents "hi". This is a typical example of a pass by reference on a method in C++.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文