在C++中返回字符串的最佳方法是什么
What is the best way to return string in C++?
我的问题很简单:如果我有一些类Man,并且我想定义返回man名称的成员函数,那么我应该更喜欢以下两种变体中的哪一种?
第一:
string name();
第二:
void name(/* OUT */ string &name);
第一个变体效率低下,因为它会产生不必要的副本(局部变量 -> 返回值 ->赋值左侧的变量)。
第二个变体看起来非常有效,但它让我哭了
string name;
john.name(name);
而不是简单
string name(john.name());
那么,我应该更喜欢哪种变体,效率和便利性/可读性之间的适当权衡是什么?
这是一个很好的问题,你问它的事实表明你正在关注你的代码。然而,好消息是,在这种特殊情况下,有一个简单的出路。
第一种,清洁方法是正确的方法。在大多数情况下,编译器将消除不必要的副本(通常是在有意义的地方)。
编辑 (6/25/2016)
不幸的是,大卫·亚伯拉罕的网站似乎已经离线了几年,那篇文章已经丢失了(没有可用的 archive.org 副本)。我冒昧地将我的本地副本作为PDF格式上传以供存档,可以在这里找到。
使用第一个变体:
string name();
编译器很可能会优化掉任何不必要的副本。请参阅返回值优化。
在 C++11 中,移动语义意味着即使编译器不执行 RVO,也不会执行完整副本。请参阅移动语义。
还要记住,如果替代方案是
void name(std::string& s);
然后,您必须非常清楚地指定s
会发生什么以及传递给函数时它可以具有的值,并且可能执行大量有效性检查,或者干脆完全覆盖输入。
既然你想为类的某个字段创建一个getter,也许你应该这样做:inline const std::string& name() const { return this->name; }
由于名称是作为 const 引用返回的,因此不会在类外部对其进行修改,也不会通过返回名称来创建副本。
之后,如果要操作名称,则必须进行复制。
我会选择第一个。返回值优化和 C++11 将消除任何复制开销。
由于我们有移动语义(在 C++11 中),您可以使用以下内容:
string name();
即使在 C++03 中,这也几乎是好的,因为编译器可能会对此进行优化(搜索返回值优化)。
优化规则#1:测量,优化,测量。或者,正如高德纳所说,"过早的优化是万恶之源"。
除非您有强烈的迹象表明简单地返回std::string
会显着影响软件的性能,否则请这样做。如果您可以衡量重大影响,请找到关键路径并对其进行优化。不要进行任何有趣的项目范围的"优化",这些优化可能不会带来很少的性能优势,但会对代码的可读性、可维护性和健壮性产生负面影响。
我认为你应该使用第一个变体。因为这是简单的吸气剂方法,并且到处都在使用这种吸气剂/设置剂方法。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?