C++ 传递标准::字符串的最快方法
C++ Fastest way to pass a std::string?
注意
,我问这个问题是作为一个std::string
特定的问题,而不是一个一般的如何传递一个对象。
我会删除这个问题,但由于它的答案,我不允许这样做。我相信答案可能倾向于回答更普遍的问题,即"在C++中传递对象的最佳方法是什么?在堆栈溢出上有许多这些更通用的答案重复,即使这个精确的问题本身可能不是一个重复的问题。这种退化可能是因为这个问题是一个不恰当的问题,并且 std::string 类没有什么特别之处。这个问题没有很高的赞成票,这表明它并不有趣。在那种情况下,我的坏。也许一个mod会看到这个黑色的文字,怜悯我并杀死这个问题。
以下哪一个签名表示将非 const std::string
实例传递到不修改它的函数中的最快方法,同时考虑到调用站点调用的总体开销,包括在调用之前是否生成基础字符数组的深层副本?
extern void eat_string_by_value (std::string s);
extern void eat_const_string_by_value (const std::string s);
extern void eat_string_by_reference (std::string& s);
extern void eat_const_string_by_reference(const std::string& s);
请注意,我问这个问题是作为一个特定于std::string
的问题,而不是一个一般的如何传递对象的问题。特别是,我的问题受到以下因素的启发:
- std::string handle-body 实现:是否有任何签名在调用站点暗示字符串主体及其后备字符数组的深层副本?
- 请注意复制句柄(应该是轻量级(和复制正文(这将涉及内存分配(之间的区别。
- C++98 与 C++>=11:这个版本分歧的两边有不同的答案吗?
我不认为我的问题与前一个问题重复,前一个问题本身被标记为传递一个的一般对象的副本<将参数传递为 或=" const=">因为这些特定于类型的详细点。将参数传递为>
关于相关问题的有趣答案:
- https://stackoverflow.com/a/10232761/506073
extern void eat_string_by_value (std::string s); // value
extern void eat_const_string_by_value (const std::string s);
extern void eat_string_by_reference (std::string& s); // reference
extern void eat_const_string_by_reference(const std::string& s); // const-ref
首先,您错过了一个选项(自C++11以来(:
extern void eat_string_by_rvaluereference(std::string&& s); // rvalue-ref
接下来,您的两个选项是相同的,因为顶级参数 cv 限定符不是函数签名的一部分:
extern void eat_string_by_value (std::string s);
extern void eat_const_string_by_value (const std::string s);
那么,让我们看看:
- 按值传递:
缺点:调用方必须复制或移动到参数中。除非它在那里建造。
优点:与所有人绑定。被调用方有自己的副本要修改。 - 通过引用:缺点:仅绑定到左值(非临时对象(。
优点:被调用方可以修改传递的参数。 - 路过常量参考。缺点:如果需要,被调用方必须制作自己的副本。
优点:对所有人都有约束力。 - 通过右值引用。
缺点:无法绑定到左值。如果绑定到常量对象,则复制。
优点:可以清除传递的参数。
因此,by-value 几乎总是意味着一个副本(或至少是一个移动(,by-reference 意味着永远不会是一个副本(但对参数有不必要的限制(,其余的只有在需要转换时才复制。
by-const-ref 表示参数不能修改,by-rvalue-ref 表示可以重用其资源,这可能会在以后保存副本。
以下哪一个签名表示将非 const st::string 实例传递到不修改它的函数中的最快方法,同时考虑到调用站点调用的总体开销,包括在调用之前是否会生成基础字符数组的深层副本?
这要看情况。没有一种方法适用于所有情况,在所有方面
。主要变量:
- 你在通过什么?字符串的长度会影响哪种形式优于其他形式。
- 编译器
- 编译器选项和语言标准
- 标准库
- 呼叫站点是否需要副本?
- 函数中的字符串会发生什么变化?
- 按值传递可以开辟一些优化的可能性,但复制的成本通常更高。
没有一个答案/签名适合每种情况。
std::string handle-body 实现:是否有任何签名在调用站点暗示字符串主体及其后备字符数组的深层副本?
一些实现使用了 COW(写入时复制(,但这在 C++11 中不再有效。传递值将需要副本。如果库实现了 SSO,则对于短字符串,复制可能很快(=无堆分配(。
C++98 与 C++>=11:这个版本分歧的两边有不同的答案吗?
如上所述,COW不再有效。您可能会看到非常不同的性能特征。
- 有哪些有效的方法可以消除一组 100 万个字符串>重复数据?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 具有字符串化的可变参数宏的现代/通用方法
- 接收字符串并使用它来调用方法C++
- 如何分隔字符串并将标记传递给方法
- 是否有通用方法可以找到任何以 null 结尾的字符串的长度?
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 在 C++11 中字符串化变量名称的替代方法
- 连接和压缩标准::vector<std::字符串的最佳方法>
- Esp8266 & Nodemcu:返回请求字符串的方法
- 将位字符串转储到二进制文件的最佳方法是什么
- 有没有一种 STL 方法可以找到字符串的所有排列,给出一个以 C++ 为单位的大小?
- 如何将字符串从 C++/CLI 方法返回到调用它的非托管C++
- 创建字符串数组的有效方法
- 如何使用字符串::replace方法写入文件
- 是否有更有效的方法来生成日期的REGEX字符串
- C++-将对象(如字符串)映射到表中成员函数的正确方法
- 有没有更快的方法从成员函数返回格式化字符串
- 有没有一种方法可以在不复制数据的情况下从string_view创建字符串流
- 从c++中的类指针对象调用方法(字符串)