引用和指针之间有什么区别?

时间:2010-11-25 22:50:44

标签: c++ pointers dynamic-memory-allocation

有人可以用非常小的词语向我解释差异吗?我从来没有理解这一点,在我目前的项目中非常困惑。我想要做的是修复此代码:

const Multinumber& Pairs::operator+(const Multinumber &rhs) const
{
    const Pairs &_rhs = dynamic_cast<const Pairs &>(rhs);
    Pairs toreturn(_rhs.X_value+X_value,_rhs.Y_value+Y_value);
    return toreturn; //reference to local variable? fix this?
}

现在我的编译器告诉我这是对局部变量的引用,但它不会让我转向返回指针,因为它们与引用有某种不同。然后,我也在研究一个set类,它应该保存对抽象类对象的引用或指针。我完全糊涂了。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

首先,你的签名是错误的。它应该是:

Multinumber Pairs::operator+(const Multinumber &rhs) const;

operator+应返回一个新对象,而不是对任一参数的引用。

至于引用和指针之间的区别,这个detailed question就在SO上。它涵盖了所有基础知识和一些基础知识。

答案 1 :(得分:1)

你看起来很困惑:)好吧,所以:

本质上,指针只是一个存储另一个变量地址的变量。例如,假设我有一个名为int的{​​{1}},我可以将其地址存储在指针i中:

p

如果我想改变它指向的东西(即它存储的地址的变量),我只是分配给int i = 23; int *p = &i; // p has type int* (pointer to int) and stores &i (the address of i) - 这是用来表示指向的东西的语法。在这种情况下,*p指的是*p。因此:

i

我可以重新分配指针(即指向其他东西)只需分配给*p = 9; // sets i to 9 (since *p is i) ,即

p

现在,参考文献略有不同。引用为变量创建别名:

int j = 84;
p = &j;     // store j's address in p, overwriting what was there before (i.e. i's address)
*p = 18;        // sets j to 18 (since *p is now j)

请注意,引用可以根据指针实现(或者它们可能不会,特别是当编译器开始优化时),但这与编程角度无关 - 这对我们来说很重要是语言的工作方式。

如果你想改变所引用的东西(在这种情况下是int i = 23; int& r = i; // r has type int& (reference to int) and refers to i ),你就是这样做:

i

与指针不同,引用无法重新定位。如上所示,分配给r = 9; // sets i to 9 (since r is an alias for i) 会更改您引用的内容(r),而不是引用本身。此外,由于无法重新引用引用,因此必须立即初始化引用。指针不是这种情况。换句话说:

i

最后一个基本区别是指针可以是int *p; // legal int& r; // bad ,表明它们没有指向任何东西。这只意味着它们包含地址NULL。引用必须始终引用实际对象。这种差异对于实现者来说很重要,因为他们可以使用指针来实现Maybe类型,即如果指针不是0,则使用指向对象,否则执行其他操作。他们不能用引用做同样的事情。

希望关于指针和参考文献清楚明白!


现在,关于你的NULL - 加法运算符的目的是添加两个对象并返回表示其总和的新对象。所以,如果我有一个2D矢量类型,我可能会为它写一个operator+,如下所示:

operator+

在您的代码中,您试图通过引用返回本地对象Vec2 operator+(const Vec2& lhs, const Vec2& rhs) { return Vec2(lhs.x+rhs.x, lhs.y+rhs.y); } - 这不起作用,因为toreturn不再存在于运算符的末尾。相反,你应该在这里返回值。顺便提一下,如果你试图返回一个指针,例如

,你会遇到同样的问题
toreturn

在该代码中,Vec2* operator+(const Vec2& lhs, const Vec2& rhs) { Vec2 result(lhs.x+rhs.x, lhs.y+rhs.y); return &result; // bad! } 不再存在于运算符的末尾,因此返回的指针最终将指向无效位置。底线 - 不要尝试任何花哨的东西,在这种情况下按价值回报。

答案 2 :(得分:0)

指针有一些对象所在的地址。引用是指针的别名,这意味着您不必取消引用它。但用法类似 - 不要复制对象,只能使用原点。

您将变量toreturn作为局部变量,这意味着编译器在方法结束时为此对象生成析构函数。所以你试图返回被破坏的物体。