正如我在c ++中所知,当你通过引用传递一个变量意味着我们传递的是非常变量而不是它的副本。因此,如果将参考作为参数的函数知道该函数对参数所做的任何更改都将影响原始变量(传入的变量)。但我现在卡住了:我有一个成员函数,它接受int这个成员函数的引用void DecrX(int& x)在调用时递减x。我得到的问题是原始变量永远不会影响??? !!!例如:
#include <iostream>
using namespace std;
class A
{
public:
A(int &X):x(X){}
int &getX(){return x;}
void DecrX(){--x;}
void print(){cout<<"A::x= "<<x<<endl<<endl;}
private:
int x;
};
int main()
{
int x=7;
cout<<"x= "<<x<<endl;
A a(x);//we passed the x by reference
a.DecrX();// here normally DecrX() affect the original x
a.print();//here it is ok as we thought
a.DecrX();
a.DecrX();
a.print();
cout<<"x= "<<x<<endl;//why x is still 7 not decremented
cout<<endl;
return 0;
}
答案 0 :(得分:3)
你可以通过更加冗长的方式让自己更容易理解这个问题,特别是给你的成员变量更多不同的名字。
class A
{
public:
A(int& x) : m_x(x) {}
const int& getX() const { return m_x; }
void DecrX() { --m_x; }
void print() {cout << "A::m_x= " << m_x << endl << endl;}
private:
int m_x;
};
现在,让我们更仔细地看一下。 “m_x”(成员x)的类型为“int”。这不是参考。这是一个价值。
A(int& x)
声明一个构造函数,它接受对变量的引用并调用此引用“x”。
: m_x(x)
初始化成员x,一个整数值,其值为x。
问题是你的成员m_x本身就是一个值,而不是一个引用。
class A
{
public:
A(int& x) : m_x(x) {}
const int& getX() const { return m_x; }
void DecrX() { --m_x; }
void print() {cout << "A::m_x= " << m_x << endl << endl;}
private:
int& m_x;
};
当心:创建引用事物的对象可能是一场噩梦。
#include <iostream>
class A
{
public:
A(int& x) : m_x(x) {}
const int& getX() const { return m_x; }
void DecrX() { --m_x; }
void print() { std::cout << "A::m_x= " << m_x << std::endl << std::endl; }
private:
int& m_x;
};
A calculateStuffAndReturnAnAForMe(int x, int y)
{
int z = x + y;
A a(z);
return a;
}
int main()
{
A badData = calculateStuffAndReturnAnAForMe(5, 10);
badData.print(); // badData's m_x is a reference to z, which is no-longer valid.
std::string input;
std::cout << "Enter your name: ";
std::cin >> input;
std::cout << std::endl << "You entered: " << input << std::endl;
badData.print();
}
在这种情况下,我们返回的“a”引用了堆栈变量“z”,但是当我们离开函数时“z”消失了。结果是未定义的行为。
查看现场演示:http://ideone.com/T279v7
答案 1 :(得分:1)
在cout<<"x= "<<x<<endl;
中打印main()
的局部变量,而在a.print()
行中打印对象x
的局部变量a
函数DecrX()
减少。
答案 2 :(得分:1)
您正在修改副本而不是原件本身,因此原件不会被更改。阅读评论:
A(int &X) : x (X) {} // This copies modifiable `X` into `x`.
| ^
| |
+--+
void DecrX(){--x;} // This decrements `x` not referenced `X`
要具备修改原始变量的能力,您应该声明一个引用:
class A
{
public:
A(int &X):x(X){}
void DecrX(){--x;}
private:
int &x; // <<------------ A reference
^
};
注意,传递变量的生命周期应该比A
的接收者对象长。
答案 3 :(得分:1)
问题是你的构造函数通过引用获取变量的事实在这里是无关紧要的:
class A
{
public:
A(int &X):x(X){} // <-- initializes member x by copying passed argument
void DecrX(){--x;} // <-- decrements member of class A
...
int x;
};
要实现您实际描述的内容,您还需要将成员x
定义为参考:
int& x;
“如果我们声明一个指针作为成员数据将与您声明引用int &x
一样吗?”
使用地址初始化指针。重要的是要知道NULL
是完全有效的值,而引用不能通过其他方式初始化,而不是使用有效的变量/对象。请注意,一旦将成员x
声明为引用,就会引入一个约束,即如果没有有效的A
变量,则无法创建类int
的实例。看看:Should I prefer pointers or references in member data?
答案 4 :(得分:0)
这里的问题是您传递引用,但随后将其分配给类成员x。这样做不会保留参考。并且x类成员和主要的x完全不相关。我希望这是有道理的。要解决此问题,您可以使类成员x成为指针。