指针变量和引用变量之间的区别是什么?
当前回答
引用是另一个变量的别名,而指针保存变量的内存地址。引用通常用作函数参数,因此传递的对象不是副本而是对象本身。
void fun(int &a, int &b); // A common usage of references.
int a = 0;
int &b = a; // b is an alias for a. Not so common to use.
其他回答
也许一些隐喻会有所帮助;在桌面屏幕空间中-
引用要求您指定实际窗口。指针需要屏幕上一块空间的位置,确保它将包含该窗口类型的零个或多个实例。
引用永远不能为NULL。
指针和引用之间有一个非常重要的非技术性区别:通过指针传递给函数的参数比通过非常量引用传递给函数参数的参数更为可见。例如:
void fn1(std::string s);
void fn2(const std::string& s);
void fn3(std::string& s);
void fn4(std::string* s);
void bar() {
std::string x;
fn1(x); // Cannot modify x
fn2(x); // Cannot modify x (without const_cast)
fn3(x); // CAN modify x!
fn4(&x); // Can modify x (but is obvious about it)
}
回到C中,一个看起来像fn(x)的调用只能通过值传递,因此它肯定不能修改x;要修改参数,需要传递指针fn(&x)。所以,如果一个参数前面没有&,你就知道它不会被修改。(相反,&表示已修改,这是不正确的,因为有时必须通过常量指针传递大型只读结构。)
一些人认为,这是读取代码时非常有用的特性,指针参数应该始终用于可修改的参数,而不是非常量引用,即使函数从不期望null指针。也就是说,这些人认为不应该允许像上面的fn3()这样的函数签名。谷歌的C++风格指南就是一个例子。
与流行观点相反,引用可能为NULL。
int * p = NULL;
int & r = *p;
r = 1; // crash! (if you're lucky)
当然,使用引用要困难得多,但如果你管理它,你会为了找到它而绞尽脑汁。引用在C++中并不安全!
从技术上讲,这是一个无效引用,而不是空引用。C++不支持在其他语言中可能会发现的空引用作为概念。还有其他类型的无效引用。任何无效引用都会引发未定义行为的幽灵,就像使用无效指针一样。
实际错误是在分配给引用之前取消引用NULL指针。但我不知道任何编译器会在这种情况下生成任何错误——错误会传播到代码中更远的地方。这就是这个问题如此阴险的原因。大多数情况下,如果取消引用NULL指针,就会在该位置崩溃,而且不需要太多调试就可以解决问题。
我上面的例子简短而做作。这是一个更真实的例子。
class MyClass
{
...
virtual void DoSomething(int,int,int,int,int);
};
void Foo(const MyClass & bar)
{
...
bar.DoSomething(i1,i2,i3,i4,i5); // crash occurs here due to memory access violation - obvious why?
}
MyClass * GetInstance()
{
if (somecondition)
return NULL;
...
}
MyClass * p = GetInstance();
Foo(*p);
我想重申,获得空引用的唯一方法是通过格式错误的代码,一旦获得了它,就会得到未定义的行为。检查空引用是没有意义的;例如,您可以尝试如果(&bar==NULL)。。。但是编译器可能会优化不存在的语句!有效引用永远不能为NULL,因此从编译器的角度来看,比较总是错误的,并且可以自由地将if子句作为死代码来消除-这是未定义行为的本质。
避免麻烦的正确方法是避免取消引用NULL指针来创建引用。这里有一种自动化的方法来实现这一点。
template<typename T>
T& deref(T* p)
{
if (p == NULL)
throw std::invalid_argument(std::string("NULL reference"));
return *p;
}
MyClass * p = GetInstance();
Foo(deref(p));
要从具有更好写作技巧的人那里了解这个问题,请参阅Jim Hyslop和Herb Sutter的空引用。
有关取消引用空指针的危险的另一个示例,请参见Raymond Chen在尝试将代码移植到另一个平台时暴露未定义的行为。
引用是另一个变量的别名,而指针保存变量的内存地址。引用通常用作函数参数,因此传递的对象不是副本而是对象本身。
void fun(int &a, int &b); // A common usage of references.
int a = 0;
int &b = a; // b is an alias for a. Not so common to use.
推荐文章
- 如何构建和使用谷歌TensorFlow c++ api
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 如何为Fedora安装g++ ?
- Std::cin输入空格?
- c++标准是否要求iostreams的性能很差,或者我只是在处理一个糟糕的实现?
- gcc在哪里查找C和c++头文件?
- 为什么我们需要require require ?
- 解析c++中的命令行参数?
- 我如何在c++中创建一个随机的字母数字字符串?
- c++中的atan和atan2有什么区别?
- 现代c++能让你免费获得性能吗?
- 一门语言是如何自我扩展的?