【问题标题】:Passing std::string by Value or Reference [duplicate]通过值或引用传递 std::string [重复]
【发布时间】:2012-06-03 02:54:42
【问题描述】:

可能重复:
Are the days of passing const std::string & as a parameter over?

如果支持移动语义,我应该通过值还是通过引用(对未内联函数)传递std::string?那么使用小字符串优化 (SSO) 的实现呢?

【问题讨论】:

  • 函数中的字符串要做什么?
  • @linuxuser27:啊,好问题。答案当然取决于……在某些情况下,我只是阅读它,在其他情况下,我将其与目录连接在一起以构建路径。我相信当我想修改它时我应该按值传递,以使移动构造函数发挥作用。只读情况如何——通过常量引用?

标签: c++ string std move-semantics


【解决方案1】:

根据您对字符串所做的操作,有多个答案。

1) 使用字符串作为 id(不会被修改)。在这里通过 const 引用传递它可能是最好的主意:(std::string const&)

2) 修改字符串但不希望调用者看到该更改。最好按值传递:(std::string)

3) 修改字符串但希望调用者看到该更改。最好通过引用传递它:(std::string &)

4) 将字符串发送到函数中,函数的调用者将不再使用该字符串。使用move semantics 可能是一个选项(std::string &&)

【讨论】:

  • Case 3) 只有在 std::string 实现不支持移动语义时才需要对吗?
  • @Nordlöw 不是真的。移动语义很有趣,因为它们移动的是数据而不是复制它。在上述情况下,移动语义会将std::string 中的char * 从调用函数移动到被调用函数。如果您使用移动语义来传递值,则字符串将不再位于调用者函数中,除非您将其传回。请参阅上面有关移动语义的链接。
  • #4 是不必要的,因为这是可以而且应该在调用者方面通过在他的参数上使用std::move 并调用按值版本来处理的事情。
  • @BenjaminLindley 一点也不,&& 可以防止意外通过副本传递参数。
  • @Destructor 它从字符串文字构造一个std::string 并将其作为参数传递。然后它从参数中复制构造成员字符串。所以两个分配和两个 O(n) 数组复制操作(每个参数)。您应该按值获取参数,并将 std::move 它们放入成员中。这样一来,每个参数只有一次分配,一次 O(n) 数组副本和一次 O(1) 移动。
【解决方案2】:

检查this answer for C++11。基本上,如果你传递一个左值,右值引用

来自this article:

void f1(String s) {
    vector<String> v;
    v.push_back(std::move(s));
}
void f2(const String &s) {
    vector<String> v;
    v.push_back(s);
}

"对于左值参数,'f1'有一个额外的副本来传递参数,因为它是按值,而'f2'有一个额外的副本来调用push_back。所以没有区别;对于右值参数,编译器必须创建一个临时的'String(L“”)'并将临时传递给'f1'或'f2'。因为'f2'可以在参数是临时的(这是一个右值)时利用移动ctor,所以成本'f1' 和 'f2' 现在传递参数是一样的。”

继续: " 这意味着在 C++11 中,我们可以在以下情况下使用 pass-by-value 方法获得更好的性能:

  1. 参数类型支持移动语义 - 所有标准库组件都在 C++11 中实现
  2. 移动构造函数的成本比复制构造函数便宜很多 (时间和堆栈使用)。
  3. 在函数内部,参数类型会被传递给另一个函数或操作 支持复制和移动。
  4. 通常将临时参数作为参数传递 - 您可以组织代码来执行更多操作。

"

OTOH,对于 C++98,最好通过引用传递 - 更少的数据被复制。传递 const 或 non const 取决于您是否需要更改参数。

【讨论】:

    【解决方案3】:

    我相信正常的答案是,如果您需要在函数中复制它,它应该按值传递。否则通过 const 引用传递它。

    这是一个很好的讨论:http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

    【讨论】:

    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2012-02-29
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多