The*_*ger 68 c++ pointers language-design reference
C++引用有两个属性:
指针是相反的:
为什么C++中没有"不可为空,可重复的引用或指针"?我想不出为什么参考不应该是可重复的一个很好的理由.
编辑: 问题经常出现,因为我通常使用引用,当我想确保"关联"(我在这里避免使用"引用"或"指针")永远无效.
我认为我从没想过"这个引用始终指的是同一个对象".如果引用是可重用的,那么仍然可以得到当前的行为:
int i = 3;
int& const j = i;Run Code Online (Sandbox Code Playgroud)
这已经是合法的C++,但毫无意义.
我重申我的问题: "'引用的背后是什么原因是对象'设计?为什么引用始终是同一个对象,而不是仅当声明为const时才被认为是有用的?"
干杯,菲利克斯
Mic*_*urr 88
Stroustrup的"C++的设计和演变"中给出了C++不允许重新引用引用的原因:
初始化后无法更改引用引用的内容.也就是说,一旦初始化了C++引用,就不能在以后引用其他对象; 它无法重新绑定.我过去曾被Algol68引用所咬,其中
r1=r2可以分配给所引用r1的对象,也可以根据类型赋予r1(重新绑定r1)新的引用值r2.我想避免在C++中出现这样的问题.
rlb*_*ond 32
在C++中,人们常说"引用是对象".从某种意义上说,确实如此:虽然在编译源代码时将引用作为指针处理,但引用旨在表示在调用函数时未复制的对象.由于引用不是可直接寻址的(例如,引用没有地址,&返回对象的地址),因此重新分配它们在语义上没有意义.而且,C++已经有了指针,它处理重新设置的语义.
jal*_*alf 18
因为那时你没有可重复的类型,不能为0.除非你包括3种类型的引用/指针.这会使语言变得非常复杂(然后为什么不添加第4种类型?不可重复的参考,可以是0?)
一个更好的问题可能是,为什么您希望引用可重新组合?如果是的话,这会使它们在很多情况下变得不那么有用.这会使编译器更难进行别名分析.
似乎Java或C#中引用的主要原因是可重用的是因为它们完成了指针的工作.他们指向对象.它们不是对象的别名.
以下是什么影响?
int i = 42;
int& j = i;
j = 43;
Run Code Online (Sandbox Code Playgroud)
在今天的C++中,使用不可重新引用的引用,它很简单.j是i的别名,我最终得到值43.
如果引用是可重新排列的,则第三行将引用j绑定到不同的值.它不再是别名,而是整数文字43(当然无效).或者可能是一个更简单(或至少在语法上有效)的例子:
int i = 42;
int k = 43;
int& j = i;
j = k;
Run Code Online (Sandbox Code Playgroud)
具有可重复的引用.在评估此代码后,j将指向k.使用C++的不可重复引用,j仍然指向i,并且我被赋值为43.
使引用可重新更改语言的语义.引用不能再是另一个变量的别名.相反,它成为一个单独的值类型,具有自己的赋值运算符.然后,最常见的参考用法之一是不可能的.没有任何东西可以获得交换.新获得的引用功能已经以指针的形式存在.所以现在我们有两种方法可以做同样的事情,而且无法用当前的C++语言做什么引用.
有趣的是,这里的许多答案都有点模糊,甚至离题(例如,这并不是因为引用不能为零或相似,事实上,您可以轻松构建一个引用为零的示例)。
无法重新设置参考的真正原因相当简单。
指针使您可以执行两件事:更改指针后面的值(通过->或*运算符),以及更改指针本身(直接赋值=)。例子:
int a;
int * p = &a;Run Code Online (Sandbox Code Playgroud)
*p = 42;p = 0;引用允许您仅更改值。为什么?由于没有其他语法来表达重新设置。例子:
int a = 10;
int b = 20;
int & r = a;
r = b; // re-set r to b, or set a to 20?Run Code Online (Sandbox Code Playgroud)换句话说,如果允许您重新设置引用,则会产生歧义。通过引用传递时更有意义:
void foo(int & r)
{
int b = 20;
r = b; // re-set r to a? or set a to 20?
}
void main()
{
int a = 10;
foo(a);
}
Run Code Online (Sandbox Code Playgroud)
希望有帮助:-)
引用不是指针,它可以在后台实现为指针,但其核心概念不等同于指针.引用应该像它*is*所指的对象一样.因此您无法更改它,也不能为NULL.
指针只是一个保存内存地址的变量. 指针本身有一个自己的内存地址,在该内存地址中它保存另一个据说指向的内存地址. 引用不相同,它没有自己的地址,因此不能更改为"保持"另一个地址.
我认为关于参考文件的parashift C++ FAQ最好说:
重要说明:尽管通常使用基础汇编语言中的地址实现引用,但请不要将引用视为指向对象的有趣外观指针.参考是对象.它不是指向对象的指针,也不是对象的副本.这是对象.
在FAQ 8.5中再次:
与指针不同,一旦引用绑定到对象,它就不能"重新"到另一个对象.引用本身不是一个对象(它没有标识;获取引用的地址会给出引用的地址;记住:引用是它的引用).
可重新引用的引用在功能上与指针相同.
关于可空性:您无法保证在编译时这样的"可重新引用的引用"是非NULL的,因此任何此类测试都必须在运行时进行.您可以通过编写一个智能指针样式的类模板来实现这一点,该模板在初始化或分配NULL时抛出异常:
struct null_pointer_exception { ... };
template<typename T>
struct non_null_pointer {
// No default ctor as it could only sensibly produce a NULL pointer
non_null_pointer(T* p) : _p(p) { die_if_null(); }
non_null_pointer(non_null_pointer const& nnp) : _p(nnp._p) {}
non_null_pointer& operator=(T* p) { _p = p; die_if_null(); }
non_null_pointer& operator=(non_null_pointer const& nnp) { _p = nnp._p; }
T& operator*() { return *_p; }
T const& operator*() const { return *_p; }
T* operator->() { return _p; }
// Allow implicit conversion to T* for convenience
operator T*() const { return _p; }
// You also need to implement operators for +, -, +=, -=, ++, --
private:
T* _p;
void die_if_null() const {
if (!_p) { throw null_pointer_exception(); }
}
};
Run Code Online (Sandbox Code Playgroud)
这可能是有用的 - 带non_null_pointer<int>参数的函数肯定会传递更多信息给调用者而不是函数int*.
| 归档时间: |
|
| 查看次数: |
19456 次 |
| 最近记录: |