C++中的指针变量和引用变量有什么区别?
我知道引用是语法糖,所以代码更容易阅读和编写.
I know references are syntactic sugar, so code is easier to read and write.
但是指针变量和引用变量有什么区别?
But what is the difference between a pointer variable and a reference variable?
一个指针可以重新赋值:
A pointer can be re-assigned:
int x = 5;
int y = 6;
int *p;
p = &x;
p = &y;
*p = 10;
assert(x == 5);
assert(y == 10);
引用不能重新绑定,必须在初始化时绑定:
A reference cannot be re-bound, and must be bound at initialization:
int x = 5;
int y = 6;
int &q; // error
int &r = x;
一个指针变量有它自己的身份:一个独特的、可见的内存地址,可以用一元 &
运算符获取,以及一定量的空间,可以用 sizeof
运算符.在引用上使用这些运算符会返回与引用绑定到的任何内容相对应的值;引用自己的地址和大小是不可见的.由于引用以这种方式假定原始变量的身份,因此可以方便地将引用视为同一变量的另一个名称.
A pointer variable has its own identity: a distinct, visible memory address that can be taken with the unary &
operator and a certain amount of space that can be measured with the sizeof
operator. Using those operators on a reference returns a value corresponding to whatever the reference is bound to; the reference’s own address and size are invisible. Since the reference assumes the identity of the original variable in this way, it is convenient to think of a reference as another name for the same variable.
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
assert(p == p2); // &x == &r
assert(&p != &p2);
您可以任意嵌套指向提供额外间接级别的指针的指针.引用仅提供一级间接.
You can have arbitrarily nested pointers to pointers offering extra levels of indirection. References only offer one level of indirection.
int x = 0;
int y = 0;
int *p = &x;
int *q = &y;
int **pp = &p;
**pp = 2;
pp = &q; // *pp is now q
**pp = 4;
assert(y == 4);
assert(x == 2);
可以为指针赋值nullptr
,而引用必须绑定到现有对象.如果你足够努力,你可以绑定一个对 nullptr
的引用,但这是 undefined 并且会行为不一致.
A pointer can be assigned nullptr
, whereas a reference must be bound to an existing object. If you try hard enough, you can bind a reference to nullptr
, but this is undefined and will not behave consistently.
/* the code below is undefined; your compiler may optimise it
* differently, emit warnings, or outright refuse to compile it */
int &r = *static_cast<int *>(nullptr);
// prints "null" under GCC 10
std::cout
<< (&r != nullptr
? "not null" : "null")
<< std::endl;
bool f(int &r) { return &r != nullptr; }
// prints "not null" under GCC 10
std::cout
<< (f(*static_cast<int *>(nullptr))
? "not null" : "null")
<< std::endl;
但是,您可以引用值为 nullptr
的指针.
You can, however, have a reference to a pointer whose value is nullptr
.
指针可以遍历数组;您可以使用 ++
转到指针指向的下一项,使用 + 4
转到第 5 个元素.这与指针指向的对象大小无关.
Pointers can iterate over an array; you can use ++
to go to the next item that a pointer is pointing to, and + 4
to go to the 5th element. This is no matter what size the object is that the pointer points to.
指针需要用*
解引用才能访问它指向的内存位置,而引用可以直接使用.指向类/结构的指针使用 ->
访问其成员,而引用使用 .
.
A pointer needs to be dereferenced with *
to access the memory location it points to, whereas a reference can be used directly. A pointer to a class/struct uses ->
to access its members whereas a reference uses a .
.
引用不能放入数组,而指针可以(由用户@litb 提及)
References cannot be put into an array, whereas pointers can be (Mentioned by user @litb)
常量引用可以绑定到临时对象.指针不能(不是没有一些间接性):
Const references can be bound to temporaries. Pointers cannot (not without some indirection):
const int &x = int(12); // legal C++
int *y = &int(12); // illegal to take the address of a temporary.
这使得 const &
在参数列表等中使用起来更方便.
This makes const &
more convenient to use in argument lists and so forth.