我决定查看是否为成员分配引用会使成员成为引用。我编写了以下代码片段来测试它。有一个简单的类Wrapper
,std::string
作为成员变量。我在构造函数中取一个const string&
并将其分配给public成员变量。稍后在main()
方法中我修改了成员变量,但是传递给构造函数的string
保持不变,为什么会这样?我认为在Java中变量会发生变化,为什么不在这段代码中呢?在这种情况下,引用究竟是如何工作的?
#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;
}
答案 0 :(得分:28)
要在构造函数中指定引用,您需要具有引用成员
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,那么它必须是指针。
答案 1 :(得分:7)
因为Wrapper::str
不是引用,所以它是一个独立的对象。因此,当您执行str = newStr
时,您正在复制字符串。
答案 2 :(得分:5)
class Wrapper
{
public:
string& str;
Wrapper(string& newStr) : str(newStr) {}
};
注意,您无法接受const string&
并将其存储在string&
中,这样做会失去常量。
答案 3 :(得分:3)
您需要使用初始化程序并声明str
作为参考,如:
class Wrapper {
public:
string &str;
Wrapper(string& newStr)
: str(newStr) {
}
};
您编写它的方式,您所做的只是复制传递给构造函数的引用的值。你没有保存参考。通过将引用声明为类成员并使用对另一个字符串实例的引用对其进行初始化,您将获得您正在寻找的行为。
答案 4 :(得分:1)
您应该将Wrapper::str
声明为string&
,而不是string
。
答案 5 :(得分:1)
您的主体变量为std::string
。
您的参数变量为const std::string&
。
引用中的const总是&#34;低级const&#34;,这意味着它修改了对象的类型而不是实际的对象。
相比之下,&#34;顶级const&#34;修改实际对象。请阅读C++ Primer on Top level const以获得澄清。
以下是传递参数时的分配方式:
const std::string& = std::str; //Values are ommited
// i.e const std::string newStr = std::string str
您正在使用 const type reference
初始化 non-const value
,这是可以接受的。您不应该使用该引用更改std::string str
的值。并且,如果您尝试在构造函数中更改newStr
的值,则将收到编译错误。
接下来,你在构造函数中做了另一个也是可以接受的赋值:
std::string = const std::string
wrap.str[0]
str
main
没有改变的事实是,尽管使用了引用来class str
实例化,class str
已经main str
它自己的对象,并没有链接到main str
。在参数中使用该引用只需将该参数链接到main str
;不是class str
到tractorException() {
try{
setVehicleID(0);
}catch(Exception e){
}
}
。
如果你的类变量被引用,那么它可能已经改变了。