将参数传递为 std::string 或 const std::string&? [复制]

Posted

技术标签:

【中文标题】将参数传递为 std::string 或 const std::string&? [复制]【英文标题】:Pass arguments as std::string or const std::string&? [duplicate] 【发布时间】:2012-12-27 02:09:51 【问题描述】:

可能重复:Is it better in C++ to pass by value or pass by constant reference?

我在编写文件系统时考虑过这个问题。

vector<string> getFiles(string path);
vector<string> getFiles(const string& path);

哪个更快?哪个更优雅?

显然path 永远不会在getFiles 方法中更改。

奖励:我使用的是 C++11。有没有办法移动语义可以加快一切?

【问题讨论】:

只有当您需要将path 的值存储在某处以备后用时,移动语义重载才可能有用。 @LightnessRacesInOrbit 为什么这个问题作为 4 年前提出的问题的重复而被关闭?该问题的答案完全忽略了移动语义并引用了 Effective C++,它纯粹为 C++98 最佳实践提供了指导。如果是这样,Scott 为什么还要费心更新这本书及其对 C++11 的建议? 【参考方案1】:

黄金法则:

“默认总是通过 const 引用传递。”

这应该是您传递函数参数时的默认选择。您根据情况需要选择了其他选项。

自定义类总是更有效。 对用户来说更直观。

【讨论】:

Not everybody agree with you @Lol4t0:查看 Timo 对 Bret 回答的评论。 @Alok IMO 最好首先编写健全的代码,而不是依赖编译器为您改进代码。您的商业编译器可能会执行优化,但是您的代码的其他用户呢?您是否希望代码的性能依赖于某些特定的编译器? @Lol4t0:谁?不是那篇文章的作者。那篇文章是关于复制省略的,它在这里不太可能做任何有用的事情。该函数要么接收 R 值,要么在任何一种情况下都不会复制。或者函数接收一个 L 值,在这种情况下,如果它通过值获取其参数,则必须复制它,但如果它通过引用获取它,则不需要。当您仍然需要副本时,复制省略很有用,但这里不需要副本。 @BenjaminLindley,不清楚,要不要copy,明天要不要,什么时候换界面就晚了。我的观点是,你不应该打电话给 smth golden rule 让人们不假思索地遵循你的规则。【参考方案2】:

在您的情况下,规范的答案是通过const&amp; 传递参数,这既是出于性能原因(保证避免复制字符串),也是因为您记录了意图。前者仅在您分析了代码并确定传递字符串是瓶颈时才重要 - 如果不是,您主要关注的是“最佳实践”,而不是产生很大的性能差异。

但是对我来说,如果我查看您的函数的签名,第二个明确指出“我只会读取您的参数而不对它做任何事情”,而第一个几乎说明您将做某事到参数,即使您在处理参数副本时所做的更改对外部不可见。

还有一个额外的好处是,通过 const 引用传递参数可以避免内存分配,如果您在没有无限内存(即所有内存)的系统上工作,这很方便。

【讨论】:

我不太确定传递引用会避免内存分配。 采用引用参数时的明显意图是因为您希望函数看到在函数执行时发生的参数更改。 (比如说,一个全局变量通过引用传递给一个也直接访问该全局变量的函数。无论全局变量是好是坏。)知道const &amp; 真正用于什么,它很明显,但我绝不会提倡它的可读性。 @Timo 只是为了进一步添加一些内容,分析可能表明 您的 应用程序在按值传递字符串方面没有瓶颈,但其他人使用了您的代码(或您自己的未来使用)可能会花费比您计划的更多的时间来复制字符串(在 OP 的示例中,可能用户使用长路径名反复调用 getFiles) - 因此即使您不遵循“最佳实践”也是一个好主意'不认为它现在会影响你,除非有什么理由不这样做。【参考方案3】:

使用 by-value 参数可能会更好。有关详细原因,请参阅此帖子 Want Speed? Pass by Value。基本上,您在调用函数的方式上为调用者和/或编译器提供了更大的灵活性。使用 const&amp; 可以强制执行过去的 C++98 最佳实践,但可能会与 C++11 中的移动语义相悖。

【讨论】:

在这种情况下,T const&amp; 可能更好。 如果意图是只读取字符串,我会同意。如果函数无论如何都要在内部复制const&amp;,那么按值是C++11中的最佳选择。 您的链接文章解决了该参数的几个非常具体的用途 - 即传入的参数在函数内部进行操作并返回。很有可能在 OP 的问题的背景下,情况并非如此。 @TimoGeusch 很公平。我假设 OP 提供了一个激发他的问题的例子,但正在寻找一个更普遍的答案。 @ybungalobill 不一定。我的意思不是性能意义上的,而是一种传达信息的方式。 const&amp; 在阅读函数声明时真的说“我想看看这个”。如果函数随后在内部复制,则声明具有误导性。

以上是关于将参数传递为 std::string 或 const std::string&? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何将非可变参数值传递给 fmt::format?

SWIG:如何包装 std::string&(通过引用传递的 std::string)

如何将 std::map 作为默认构造函数参数传递

将 std::string 的向量转换为 char***

如何使用 Unicode 集将 std::string 传递给 CreateDirectory

如何将 std::string 环境块传递给 CreateProcess?