【问题标题】:Which combination of overloads is most performant?哪种重载组合的性能最高?
【发布时间】:2015-02-19 05:35:52
【问题描述】:

我有这样的功能:

void init_str(std::string _s)
{
    std::string s{_s};
}

我想通过允许const char* 重载来进行优化,以避免创建临时std::string

void init_str(const char* c)
{
    std::string s{c};
}

但我也可以使用转发。

template<typename T>
void init_str(T&& t)
{
    std::string s{std::forward<T>(t)};
}

但是编译器对重载的偏好是:

  • const char*
  • 转发
  • std::string

那么我应该更喜欢哪种重载组合呢?

【问题讨论】:

  • 应该没有显着差异。如果您对这些事情有疑问,请测量。
  • 无论如何,该功能将被完全优化。真正的答案将取决于真正的功能。
  • 我会按照@πάνταῥεῖ 所说的话。 std::string_view (TS) 也可能是一个很好的解决方案(矫枉过正?)
  • 您的第一个示例通过副本接受字符串,然后您制作另一个副本,表明您需要两个副本。但是您的const char* 示例只给您留下一个字符串。如果您真的只需要一个字符串,那么您的第一个示例不需要将参数复制到第二个字符串。此外,它的构造函数应该根据传入的内容做出最佳选择,因为它具有移动语义。如果你只想要一个字符串,你可能没有比这更好的了。只需复制接受参数,不要重新复制。
  • T&amp;&amp; t 将根据作为其参数传递的原始字符串文字的长度创建一个单独的函数模板特化,除非您有 const char* c 重载

标签: c++ string performance c++11


【解决方案1】:

假设 c++11 或更高版本,性能最高的解决方案是您尚未尝试过的解决方案:

void init_str(std::string s)
{
  // just use s
}

因为复制省略将确保根本不会构造不必要的临时对象。

this 使用 std::string(const char*) 构造函数构造 s(总共 1 个构造函数):

init_str("xxx");

this 用复制构造函数构造 s:

std::string x; // 1 constructor
init_str(x);   // 1 copy constructor

this 用移动构造函数构造 s

std::string x;            // 1 constuctor
init_str(std::move(x));   // 1 move constructor

这实际上根本没有创建临时:

std::string get_str() {
    std::string s("xxx");   // 1 constructor, but...
    return s;               // ...because of RVO it's constructed at the call site
}

init_str(get_str());        // ... which is actually the constructor of s in init_str's arg list
// ... total constructors: 1

【讨论】:

    【解决方案2】:

    首先考虑你的输入参数:

    void init_str(std::string s)
    {
        // use s here ...
    }
    

    无论你调用什么函数,std::string 构造函数都会做最有效的事情。

    如果您使用临时调用,它将被移动 (std::move())。如果您使用const char* 调用它,它将通过重载的std::string() 构造函数有效复制.

    因此,您无法真正提高创建参数字符串的效率。

    您的问题不清楚是要两个字符串还是只需要一个。如果您的函数中需要两个字符串,那么:

    void init_str(std::string s1)
    {
        std::string s2 = s1;
    
        // use s1 & s2 here ...
    }
    

    鉴于您想要一个参数字符串的副本,那么 moving 不是一个选项。你不能比简单地使第二个字符串等于第一个字符串更好。 std::string 赋值运算符拥有制作最高效副本所需的所有信息。

    我看不出您的任何其他解决方案如何改进这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多