我遇到了一些使用这样的方法的代码:
QList<Item*> itemList;
void addItem(Item* const& item)
{
itemList.append(item);
}
现在,我看不出它与此之间有任何有意义的区别:
QList<Item*> itemList;
void addItem(Item* item)
{
itemList.append(item);
}
但显然有人不顾一切地使用这种奇怪的类型。或许重构工具可能出错了。
有没有充分的理由保留该功能签名?某种表现不同的角落案例?我什么都想不到。
答案 0 :(得分:6)
唯一的区别是,在第一个版本中,您不允许更改函数内的本地item
的值(您仍然可以修改它指向的Item
)。因此,如果您希望Item*
由于某种原因保持不同的值,您将被迫使用另一个类型Item*
的本地,并且该函数将消耗额外的sizeof(intptr_t)
个字节的堆栈空间(嘘声)。
我知道,不是惊天动地。
答案 1 :(得分:1)
它是对const指针的引用,这意味着你得到了这个指针的昵称,但是你无法改变它所指向的地址。
指针副本等同于是,如果你也使它成为常量。
我闻到了一系列历史变化,这些变化使得代码达到了这一点,当然经过多次命名重构。
答案 2 :(得分:1)
第一个声明意味着“item是一个常量指针引用变量”。你不能将项目更改为指向ITEM类型的另一个数据,并且它也是一个引用,因此它指向在被调用函数中作为参数传递的指针。
伪代码:Item * myItem = new Pen(); 的AddItem(myItem); 第一个声明确保additem函数不会更改pen对象,因为它是一个常量引用,它也不会复制myItem的内容,它只是指向myItem的内存位置。 而第二个声明有复制myItem内容的开销。
答案 3 :(得分:0)
它是对可变值的常量指针的可变引用。
引用将允许您修改它的引用,但它恰好发生引用类型是一个常量指针,因此指针的值不能更改。可以更改指针指向的值。
void* const &
直接传递常量指针将是等效的。
void* const
答案 4 :(得分:0)
我发生的另一个显着差异是在堆栈上传递的实际数据。在Item*
版本中,Item*
作为参数传递,需要一个取消引用才能获得Item
值。但是,由于引用是通过传递指针在最终机器代码中实现的,Item* const&
版本实际上传递Item**
作为参数,需要两个解引用来获取{{ 1}}值。
这也解释了为什么你需要额外的堆栈空间来获得可修改的Item
版本 - 你的调用者实际上没有在堆栈(或寄存器)中给你一个Item*
可以乱用,你只有一个Item*
(或C {+ Item**
)。