你似乎很困惑:) 好的,所以:
本质上,指针只是一个存储另一个变量地址的变量。例如,假设我有一个int
被调用的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
,表示它们没有指向任何东西。这只是意味着它们包含地址0
。引用必须始终引用实际对象。这种差异对实现者来说可能很重要,因为他们可以使用指针来实现 Maybe 类型,即如果指针不是NULL
,则使用指向的对象,否则执行其他操作。他们不能对引用做同样的事情。
希望关于指针与引用的问题很清楚!
现在,关于您的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!
}
在该代码result
中,运算符末尾不再存在,因此您返回的指针最终将指向无效位置。底线——不要尝试任何花哨的东西,在这种情况下按值返回。