除了考虑什么时候使用which之外,我仍然不确定指针和引用的语义。
现在,我的印象是引用本质上是指针,必须在声明它们时初始化,然后从那时起不能指向任何其他东西。(不是Type const*
),或者,它们不能被 * 重新赋值 *。它本质上变成了那个对象的“新名称”。现在我听说引用实际上不需要由编译器使用指针来实现,但我的印象是,你仍然可以这样想他们,关于他们的可见行为将是什么。
但你为什么不能做这样的事:
int& foo = new int;
我想创建一个对动态内存的引用。这不能编译。我得到错误
error: invalid initialization of non-const reference of type 'int&' from a temporary of type 'int*'
这对我来说是有意义的。似乎new操作符返回一个给定类型的指针,指向操作系统动态分配给我的内存地址。
那么,如何创建对动态内存的“引用”呢?
编辑:如果能提供精确解释C++中引用和指针之间区别的资源链接,我们将不胜感激。
4条答案
按热度按时间rks48beu1#
new
返回一个指向已分配内存的指针,因此需要在指针中捕获返回值。你可以在分配完成后创建一个指针的引用。
然后在使用后将其删除为:
或者更简单地,
使用后删除:
qfe3c7zg2#
引用是语法糖,它允许使用点操作符而不是箭头来访问对象。
你选择使用指针还是引用是 * 语义 * 的。当你通过引用传递一个对象给一个方法,或者从一个方法返回一个引用时,你是在说:“这是我的对象,你可以使用它,但我拥有它(它可能在堆栈或堆上)。”因此,这里的其他答案建议像
delete &foo;
这样的语法可能在技术上可行,但味道不好;如果你有一个对象的引用,那么你不应该删除它。你不拥有它,最重要的是,因为你不能重置引用,你最终会得到一个对释放内存的引用,这是一件坏事。现在,如果你已经在堆上分配了一个对象(称为'new'来创建它),那么你确实拥有它,并且负责稍后清理它,所以你需要持有一个指向它的指针。为什么?这样你就可以安全地删除它并将指针空出来。
指针和引用之间的区别,除了使用点而不是箭头的机械区别之外,就是通过引用传递给方法,你指示了应该如何使用对象。通过调用new直接初始化引用是毫无意义的,即使可能。
iqjalb3h3#
你可以得到这样的引用:
一般来说,要从
T*
获取到T&
,您可以使用*
来“解引用”指针。然而这并不是一个好主意,你通常使用指针来存储堆分配对象的地址。
utugiqy64#
如何引用数组
通过数组引用,我将一个堆栈数组变成了一个堆数组,而不需要大量重写我的软件。总共更改了三行代码,在类声明,构造函数和析构函数中。
栈版本
heap版本
详细说明
不要因为别人告诉你如何编写软件而感到厌烦,比如说“不要那样做”。他们的方式可能更好,但这是你自己的决定,告诉你不要做某件事并不是对“我怎么能做?"这个问题的回答,即使你想做的事情很糟糕。
我来这里寻找一个快速解决我的问题的方法。我写了一个Eratosthenese程序作为基准程序来测试我自己的素数生成器,并让它在小数字上工作得很好,以检查它的操作。我扩大了筛数组的大小,以计算更多的素数,并有堆栈大小的问题,正如我们可能预料到的那样。我想取代
简单的
这样,一旦我从
new
语句(在我的Sieve类构造函数中)初始化了reference
,当然也用delete
(在类析构函数中)整理好了,整个工作软件就可以不加修改地继续工作。我反对被告知我太懒了,不能用-〉替换.,并且应该在整个软件中使用指针。作为我类的私有成员,我可以在没有. or -〉的情况下访问数据,非常感谢!我不想重写我的成员函数访问数据,只是因为我从堆栈上的数组切换到堆上的数组。
所以,让我们分解一下我从堆栈数组切换到堆数组所做的事情,使用数组引用来避免主要的rewite。
这是一个新的指针,指向堆上新创建的数组。
是指针的类型:一个指向所需大小的布尔数组的指针。
要初始化我的引用成员,我需要在构造函数的成员初始化列表中进行……
其中上面的
...
是引用需要初始化的对象。我们即将谈到这一点,所以请耐心等待一会儿。引用通过使用对象初始化,编译器找到它的地址。由于我们有指针,我们需要使用*
来引用new
找到的对象,而不是它的地址。因此,将查找指针与
new
结合起来,将其转换为正确的类型,然后获取它所指向的对象,我们有这是类成员初始化列表中所需的内容:我们上面的
...
。所以我们有在析构函数中需要相反的方法。数组需要是
delete
d。其中,
...
与new
返回的指针值相同。在我们的例子中它是引用数组的地址
所以我们有