是否有任何实际的用例可以通过常量引用而不是按值传递指针?

Is there any realistic use case for passing pointers by constant reference rather than by value?

提问人:Enlico 提问时间:7/14/2022 最后编辑:Enlico 更新时间:7/15/2022 访问量:168

问:

由于引用 () 的行为为常量指针 (),因此通过“对指针的常量引用”参数 () 传递参数似乎有点多余,因为some-type&some-type * constsome-type * const&

  • 如果参数为some-type *
    • 我正在复制它,
    • 我无法编辑原始内容,因为我就是不处理它;
  • 如果参数为some-type * const&
    • 我不是在复制它,
    • 我无法编辑原始内容,因为我将其视为一个实体。const

因此,在某种程度上,两者之间的唯一区别是前者会产生副本,而后者则不会。

反过来,这意味着这种差异对于 s 来说可能相对重要,它可能比原始指针和 s 更大。std::shared_ptrstd::unique_ptr

但是,这是否(如果它们很“重”,则传递 s)是传递指针参数的唯一用例?std::shared_ptrconst&const&


关于问题的指针方面是不必要的观察,我认为在谈论非类似指针的数据类型时,很容易看到按值传递它们的最大优势(或最大优势之一):在这两种情况下,您都保护调用站点的实际实体, 但在后者中,您可以避免复制潜在的巨大对象。const&

对于类似指针的实体,例如原始指针和智能指针,我将它们视为至少在大小上彼此相似的东西,并允许与相似性不同。std::shared_ptr

无论如何,如果我们处理的是明显的小原始指针和 s 和小 s,以便我们可以考虑上述传递可以忽略不计的优势,那么我可能想要传递它们还有其他原因吗?std::unique_ptrstd::shared_ptrconst&const&

C++ 指针 引用 RAW-Pointer Pass-by-const-reference

评论

0赞 Eljay 7/14/2022
引用不一定在后台实现为常量指针。一些编译器可能会将其用作实现细节,但该自同一编译器也可能使用不依赖于该方法的其他机制。
1赞 Passer By 7/14/2022
指针和智能指针是不同的东西。你在问什么?
0赞 StoryTeller - Unslander Monica 7/14/2022
第一句话真的很触发
0赞 apple apple 7/14/2022
不限于指针,您的问题也可能适用于 和 。intconst int&
0赞 Pepijn Kramer 7/14/2022
TLDR 没有引用不是指针。事实上,您应该首先查看 STL 数据类型(容器),然后查看非原始指针,例如 std::unique_ptr(用于手动分配的内存或多态性用例)。仅当您非常确定(可选对象或多态对象)的生存期时,才使用原始指针。也许你应该阅读:isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines 并查找任何指针。

答:

2赞 463035818_is_not_an_ai 7/14/2022 #1

如果没有引用,则无法根据参数的恒定性重载函数:

void foo(int* const) { /* do something */ }
void foo(int*) { /* do something else */ }  // error : redefinition of foo

但是您可以使用常量/非常量引用来做到这一点:

void bar(int*&) { std::cout << "non-const\n";}
void bar(int* const&) { std::cout << "cosnt\n";}

int main() {
    int* y = nullptr;
    int* const x = nullptr;
    bar(y);
    bar(x);
}

评论

0赞 463035818_is_not_an_ai 7/14/2022
@PasserBy,调用不明确bar(int*)bar(int*&)bar(y)
0赞 463035818_is_not_an_ai 7/14/2022
@PasserBy问题中的两个签名,因为我试图提出一个支持的观点。也许我遗漏了一些东西,但我不明白如何在不使用引用的情况下重载函数some-type * const&
1赞 user253751 7/14/2022
你为什么要这样做?
0赞 Paul Sanders 7/15/2022
@user253751 这是一个很好的问题。
0赞 Goswin von Brederlow 7/15/2022
除非您打算修改局部变量,否则应始终使用该版本。但不是版本,而是使用 .同样的事情,但更容易使用。如果您遵循 C++ 核心指南,则非常量版本几乎没有意义。原始指针应始终指向单个元素,因此除了完全替换(例如)之外修改它没有任何意义。constconstint&node = node->next
2赞 Paul Sanders 7/15/2022 #2

要回答您的问题标题,对于原始指针,不。通过引用传递指针通常更昂贵,如果它是引用,则无论如何都不能使用它来修改调用者的指针,因此没有任何好处(我真的不知道@463035818_is_not_a_number在做什么,谁会想要这样的重载?const

对于智能指针,情况就不同了。 根本无法按值传递(因为复制构造函数已被删除),因此您可以通过引用传递(如果您只想获取它指向的内容),也可以从中移动(以转移所有权)。事实上,通过引用传递它并没有多大意义,因为你可以作为一个原始指针 - 按值 - 并且不会丢失任何东西。std::unique_ptrconstmy_unique_ptr.get()

std::shared_ptr 可以按值传递,但这样做会增加引用计数(然后在副本超出范围时再次递减引用计数),并且存在与此相关的成本,因此您可能希望通过引用传递它,因为这可能更便宜。但是,同样,如果您调用的函数是非所有权的,为什么不直接传递一个原始指针呢?这是最便宜的选择。const

复制 a 的唯一原因是确保它所管理的指针不会从你脚下消失,这意味着你出于某种原因(所谓的“共享所有权”)紧紧抓住它。所以,是的,如果这是你想要的语义,通过引用传递它并在接收端制作一个副本。shared_ptrconst