通过引用传递给构造函数

Posted

技术标签:

【中文标题】通过引用传递给构造函数【英文标题】:Passing by reference to a constructor 【发布时间】:2012-03-19 09:42:29 【问题描述】:

我决定看看为成员分配引用是否会使成员成为引用。我写了下面的sn-p来测试它。有一个简单的类Wrapper,其成员变量为std::string。我在构造函数中取一个const string& 并将其分配给公共成员变量。后来在main()方法中我修改了成员变量,但是我传递给构造函数的string没有改变,怎么会?我认为在Java中变量会改变,为什么不在这段代码sn-p中?在这种情况下,引用究竟是如何工作的?

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

class Wrapper

public:
   string str;

   Wrapper(const string& newStr)
   
      str = newStr;
   
;

int main (int argc, char * const argv[]) 

   string str = "hello";
   cout << str << endl;
   Wrapper wrapper(str);
   wrapper.str[0] = 'j'; // should change 'hello' to 'jello'
   cout << str << endl;

【问题讨论】:

C++ 中的类型是你规定的,它们不会神奇地变成别的东西。你说string,你得到一个string。如果你想要一个参考,你会说string &amp; 你用太简单的问题虐待别人:) 在 Java 中,变量不会改变,因为代码甚至还没有编译; Java中的字符串不允许修改。 【参考方案1】:

因为Wrapper::str 不是引用,所以它是一个独立的对象。因此,当您执行str = newStr 时,您正在复制 字符串。

【讨论】:

【参考方案2】:

您应该将Wrapper::str 声明为string&amp;,而不是string

【讨论】:

【参考方案3】:

要在构造函数中分配引用,您需要有一个引用成员

 class A
     std::string& str;
 public:
     A(std::string& str_)
     :    str(str_)  
 ;

str 现在是对您传入的值的引用。同样适用于 const refs

 class A
     const std::string& str;
 public:
     A(const std::string& str_)
     :    str(str_)  
 ;

但是不要忘记,一旦分配了引用,它就无法更改,因此如果分配需要更改 str,那么它必须是一个指针。

【讨论】:

【参考方案4】:

您需要使用初始化程序并将str 声明为引用,如下所示:

class Wrapper 
public:
   string &str;

   Wrapper(string& newStr)
      : str(newStr) 
   
;

按照您编写它的方式,您所做的只是复制您传递给构造函数的引用的值。您没有保存参考。通过将引用声明为类成员并使用对另一个字符串实例的引用对其进行初始化,您将获得所需的行为。

【讨论】:

您的代码尝试使用对常量的引用来初始化对可变的引用。 已修复...这就是我从 OP 盲目复制得到的结果。【参考方案5】:
class Wrapper

public:
   string& str;

   Wrapper(string& newStr) : str(newStr) 
;

注意,您不能接受 const string&amp; 并将其存储在 string&amp; 中,这样做会失去 const 正确性。

【讨论】:

【参考方案6】:

您的主体变量是std::string

你的参数变量是const std::string&amp;

引用中的 const 始终是“低级 const”,这意味着它修改了对象的类型,而不是实际的对象。

相比之下,“***常量”修改了实际对象。阅读C++ Primer on Top level const 以获得澄清。

当你传递参数时,你的赋值是这样的:

const std::string& = std::str; //Values are ommited
// i.e const std::string newStr = std::string str

您正在使用可接受的 non-const value 初始化 const type reference。您不应该使用该引用更改 std::string str 的值。而且,如果您尝试在构造函数中更改 newStr 的值,您将收到编译错误

接下来你在构造函数中做另一个赋值,这也是可以接受的:

std::string = const std::string 

wrap.str[0] 没有改变mainstr 的事实是,尽管使用引用来实例化class strclass str 有它自己的对象并且没有链接到main str。在参数中使用该引用只是将该参数链接到main str;不是main strclass str

如果你的类变量被引用,那么它可能已经改变了。

【讨论】:

以上是关于通过引用传递给构造函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥在通过 const 引用传递临时值时调用复制构造函数?

std::thread 通过引用传递调用复制构造函数

传递给构造函数的临时对象的 C++ 寿命

虚函数总结

禁用复制构造函数和赋值运算符时将引用实例传递给静态方法

构造函数的最佳形式?通过值或引用传递?