对指针的引用与对 int 的引用
reference to a pointer vs reference to an int
当我们创建对 int 的 引用时,我们 无法重新分配 对其他变量的引用,例如:
int a = 100;
int a1 = 200;
int &b = a;
&b = a1; // will get an error
但是,当我们创建一个对指针的引用时,似乎可以将对指针的引用重新分配给其他指针(编译器在编译时不检查时间)像这样:
int main()
{
int* p;
int* p1;
int t = 100;
int t1 = 200;
int*& ref = p;
ref = &t;
*&ref = p1;
cout << p << endl;
cout << *p << endl;
cout << ref << endl;
*&ref = p1;
ref = &t1;
cout << p1 << endl;
cout << *p1 << endl; //segmentation fault
cout << ref << endl; //segmentation fault.
return 0;
}
我不明白为什么编译器不检查我们是否将对指针的引用重新分配给另一个指针。这是 g++ 的设计方式还是我遗漏了一些概念?
您不是在重新分配引用(这是不可能的),而是在更改引用所指向的指针的值。
没有区别
*&ref = p1;
和
ref = p1;
两者都将地址从 p1
1 复制到作为引用目标的指针中,都不改变引用。并且不再与p1
有联系,所以写ref = &t1;
不会赋值给p1
.
特别是&ref
等于&p
,因为引用是透明的。所有运算符都会影响指向的对象,none 会影响引用本身。
(微妙的澄清,lambda 按引用捕获实际上可以捕获引用本身,而不仅仅是目标对象......但这不是一个运算符......如果它们包含在内部,你可以对引用本身进行操作结构,并且您在操作父结构时破坏了类型安全,但试图覆盖引用会导致未定义的行为,您可以安全地做的就是从中读取)
1 由于 p1
未初始化,复制它已经是未定义的行为。
正如其他人已经提到的,您没有重新绑定 'ref'。您将绑定变量 'p' 指向的地址指向 'p1',然后将该地址指向 t1。
p1 一直未初始化,因此 cout << *p1 << endl 是取消引用和未初始化的值(它恰好有一个地址超出您的内存 space)。
您的示例不是 "reassigning" 参考。
引用是指针。您的代码正在更改所引用指针的值。它没有更改引用,因此它引用了不同的指针。
尝试语句
cout << p << ' ' << ref << endl;
您会看到它们都打印了相同的地址,因为 ref 已被初始化为对 p 的引用。每当分配 p 或 ref 时,该值自然会发生变化(例如 "p = &some_variable" 或 "ref = &some_other_variable"),但两者将始终同步。
当我们创建对 int 的 引用时,我们 无法重新分配 对其他变量的引用,例如:
int a = 100;
int a1 = 200;
int &b = a;
&b = a1; // will get an error
但是,当我们创建一个对指针的引用时,似乎可以将对指针的引用重新分配给其他指针(编译器在编译时不检查时间)像这样:
int main()
{
int* p;
int* p1;
int t = 100;
int t1 = 200;
int*& ref = p;
ref = &t;
*&ref = p1;
cout << p << endl;
cout << *p << endl;
cout << ref << endl;
*&ref = p1;
ref = &t1;
cout << p1 << endl;
cout << *p1 << endl; //segmentation fault
cout << ref << endl; //segmentation fault.
return 0;
}
我不明白为什么编译器不检查我们是否将对指针的引用重新分配给另一个指针。这是 g++ 的设计方式还是我遗漏了一些概念?
您不是在重新分配引用(这是不可能的),而是在更改引用所指向的指针的值。
没有区别
*&ref = p1;
和
ref = p1;
两者都将地址从 p1
1 复制到作为引用目标的指针中,都不改变引用。并且不再与p1
有联系,所以写ref = &t1;
不会赋值给p1
.
特别是&ref
等于&p
,因为引用是透明的。所有运算符都会影响指向的对象,none 会影响引用本身。
(微妙的澄清,lambda 按引用捕获实际上可以捕获引用本身,而不仅仅是目标对象......但这不是一个运算符......如果它们包含在内部,你可以对引用本身进行操作结构,并且您在操作父结构时破坏了类型安全,但试图覆盖引用会导致未定义的行为,您可以安全地做的就是从中读取)
1 由于 p1
未初始化,复制它已经是未定义的行为。
正如其他人已经提到的,您没有重新绑定 'ref'。您将绑定变量 'p' 指向的地址指向 'p1',然后将该地址指向 t1。
p1 一直未初始化,因此 cout << *p1 << endl 是取消引用和未初始化的值(它恰好有一个地址超出您的内存 space)。
您的示例不是 "reassigning" 参考。
引用是指针。您的代码正在更改所引用指针的值。它没有更改引用,因此它引用了不同的指针。
尝试语句
cout << p << ' ' << ref << endl;
您会看到它们都打印了相同的地址,因为 ref 已被初始化为对 p 的引用。每当分配 p 或 ref 时,该值自然会发生变化(例如 "p = &some_variable" 或 "ref = &some_other_variable"),但两者将始终同步。