对指针的常量引用

发布于 2024-10-26 16:27:11 字数 380 浏览 1 评论 0原文

我遇到了一些使用这样的方法的代码:

QList<Item*> itemList;
void addItem(Item* const& item)
{
    itemList.append(item);
}

现在,我看不出那个和这个之间有任何有意义的区别:

QList<Item*> itemList;
void addItem(Item* item)
{
   itemList.append(item);
}

但显然有人不遗余力地使用这样一个奇怪的类型。或者也许重构工具出了严重错误。

有什么充分的理由保留该函数签名吗?某种行为不同的极端情况?我想不出什么。

I came across some code that used a method like this:

QList<Item*> itemList;
void addItem(Item* const& item)
{
    itemList.append(item);
}

Now, I can't see any meaningful difference between that and this:

QList<Item*> itemList;
void addItem(Item* item)
{
   itemList.append(item);
}

But obviously someone went way out of their way to use such an odd type. Or perhaps a refactoring tool went horribly wrong.

Is there any good reason to keep that function signature? Some sort of corner case that behaves differently? I can't think of anything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

被翻牌 2024-11-02 16:27:11

唯一的区别是,在第一个版本中,您不允许更改函数内本地 item 的值(您仍然可以修改它指向的 Item) 。因此,如果您出于某种原因希望 Item* 保存不同的值,您将被迫使用另一个 Item* 类型的本地变量,并且该函数将消耗额外的sizeof(intptr_t) 字节的堆栈空间 (boo hoo)。

我知道,这并不惊天动地。

The only difference is that in the first version you would not be allowed to change the value of the local item inside the function (you could still modify the Item it points to). Therefore if you wanted an Item* to hold a different value for some reason, you 'd be forced to use another local of type Item* and the function would consume an additional sizeof(intptr_t) bytes of stack space (boo hoo).

Not earthshaking, I know.

凉墨 2024-11-02 16:27:11

它是对 const 指针的引用,这意味着您会为此指针获得一个昵称,但无法更改它指向的地址。

指针副本是等效的,如果你也将其设置为 const 的话。

我闻到了历史上一系列的变化,这些变化使代码达到了这一点,当然是在多次命名重构之后。

It's a reference to a const pointer, meaning that you get a nickname for this pointer but you can't change the adress it points to.

A pointer copy is equivalent yes, if you make it const too.

I smell a historical sequence of changes that got the code to this point, certainly after several naming refactoring.

好倦 2024-11-02 16:27:11

第一个声明的意思是“item 是一个常量指针引用变量”。您无法更改该项目以指向 ITEM 类型的另一个数据,而且它也是一个引用,因此它指向在被调用函数中作为参数传递的指针。

伪代码:Item* myItem = new Pen();
添加项目(我的项目);
第一个声明确保 additem 函数不会更改 pen 对象,因为它是一个常量引用,也不会复制 myItem 的内容,它只是指向 myItem 的内存位置。
而第二个声明有复制 myItem 内容的开销。

The first declaration means "item is a constant pointer reference variable". You cant change the item to point to another data of type ITEM, and also it's a reference so it points to the pointer which is passed as an argument in the called function.

Pseudo code: Item* myItem = new Pen();
additem(myItem);
first declaration makes sure that the additem function wont change the pen object since it is a constant reference also it wont copy the contents of myItem, it just points to the memory location of myItem.
Whereas second declaration has an overhead of copying the content of myItem.

无风消散 2024-11-02 16:27:11

它是对指向可变值的常量指针的可变引用。

引用允许您修改它所引用的任何内容,但碰巧引用的类型是常量指针,因此指针的值无法更改。指针指向的值是可以改变的。

void* const &

  • 原始指针:不可变
  • 引用指针:不可变
  • 原始值:可变

直接传递常量指针是等效的。

void* const

  • 原始指针:不可变
  • 复制指针:不可变
  • 原始值:可变

It is a mutable reference to a constant pointer to a mutable value.

The reference would allow you to modify whatever it is a reference of, but it just so happens the referred type is a constant pointer, so the value of the pointer can't be changed. The value pointed to by the pointer can be changed.

void* const &

  • Original Pointer: Immutable
  • Referenced Pointer: Immutable
  • Original Value: Mutable

Passing a constant pointer directly would be equivalent.

void* const

  • Original Pointer: Immutable
  • Copied Pointer: Immutable
  • Original Value: Mutable
往日情怀 2024-11-02 16:27:11

我发现的另一个显着差异是在堆栈上传递的实际数据。在 Item* 版本中,Item* 作为参数传递,需要一次取消引用才能获取 Item 值。但是,由于引用是通过传递指针在最终机器代码中实现的,因此 Item* const& 版本实际上传递 Item** 作为参数,需要两个 取消引用以获取 Item 值。

这也解释了为什么您需要额外的堆栈空间来获取可修改的 Item* 版本 - 您的调用者实际上并没有在堆栈上(或在一个寄存器),你可以乱搞,你只有一个 Item** (或者在 C++ 领域中的 Item* const& )。

One additional significant difference that occurs to me is that the actual data that is passed on the stack. In the Item* version, an Item* is passed as an argument, needing one dereference to get at the Item value. However, since references are implemented in the final machine code by passing pointers, the Item* const& version actually passes an Item** as an argument, needing two dereferences to get at the Item value.

This also explains why you'd need extra stack space to get a modifiable Item* version - Your caller didn't actually give you an Item* on the stack (or in a register) that you can mess around with, you only have a Item** (or Item* const& in C++ land).

早乙女 2024-11-02 16:27:11

可能是从模板复制的。

template<class T>
class hashBase {
    virtual int hash( const T& c ) = 0;
    // other stuff: save hash, compare, etc.
};

class intHash : hashBase<int> {
    int hash( const int& c ) override { /* c=1; ERROR */ return 1; }
};

struct structData{ int a; };
class structHash : hashBase<structData> {
    int hash( const structData& c ) override { /* c.a=1; ERROR */ return 1; }
};

class structPtrHash : hashBase<structData*> {
    int hash( structData* const& c ) override { c->a=1; return 1; }
};

我想创建一个通用类来计算哈希值。

intHash:设置参数为常量
structHash:将签名更改为引用
structPtrHash:它编译的唯一方法

我达到了这个寻找“对常量指针的引用”的任务,
这在我的代码中没有实现。

此问题的热门评论:
const 和 const 有什么区别int*、const int * const 和 int const *?

推荐:
顺时针/螺旋规则
cdecl.org

我的案例的正确模式:

class constStructPtrHash : hashBase<const structData*> {
    int hash( const structData* const& c ) override { /* c->a=1; ERROR */ return 1; }
};

Might have been copied from a template.

template<class T>
class hashBase {
    virtual int hash( const T& c ) = 0;
    // other stuff: save hash, compare, etc.
};

class intHash : hashBase<int> {
    int hash( const int& c ) override { /* c=1; ERROR */ return 1; }
};

struct structData{ int a; };
class structHash : hashBase<structData> {
    int hash( const structData& c ) override { /* c.a=1; ERROR */ return 1; }
};

class structPtrHash : hashBase<structData*> {
    int hash( structData* const& c ) override { c->a=1; return 1; }
};

I wanted to make a generic class to calculate hashes.

intHash: set the parameter as constant
structHash: changed the signature to reference
structPtrHash: the only way it would compile

I reached this questing looking for "reference to a pointer of a constant",
which was not achieved in my code.

The top comments of this question:
What is the difference between const int*, const int * const, and int const *?

recommends:
Clockwise/Spiral Rule
cdecl.org

The correct pattern for my case:

class constStructPtrHash : hashBase<const structData*> {
    int hash( const structData* const& c ) override { /* c->a=1; ERROR */ return 1; }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文