0

正如我在 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;
}
4

5 回答 5

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

于 2013-10-12T21:19:39.890 回答
1

cout<<"x= "<<x<<endl;您打印的局部变量中main(),而在行中a.print()您打印的局部变量xobject a,其成员函数DecrX()减少。

于 2013-10-12T21:03:48.337 回答
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

于 2013-10-12T21:04:05.993 回答
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;
};

要实现您实际描述的内容,您还需要将 member 定义x为参考:

int& x;

“如果我们将指针声明为成员数据,将与您声明引用一样int &x吗?”

使用地址初始化指针。重要的是要意识到这NULL是完全有效的值,而除了使用有效的变量/对象之外,不能通过其他方式初始化引用。请注意,一旦将成员声明x为引用,就会引入一个约束,即没有有效变量A就无法创建类的实例。int看看:我应该更喜欢成员数据中的指针还是引用?

于 2013-10-12T21:05:23.443 回答
0

这里的问题是您传递了引用,然后将其分配给了类成员 x。这样做不会保留参考。并且 x 类成员和 main 中的 x 完全不相关。我希望这是有道理的。要解决此问题,您可以使类成员 xa 指针。

于 2013-10-12T21:07:35.553 回答