过载的哪种组合最具性能?

时间:2014-12-20 12:40:11

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

我有这样的功能:

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

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

2 个答案:

答案 0 :(得分:7)

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

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

因为复制省略将确保根本不构建任何不必要的临时。

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

init_str("xxx");

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

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

使用移动构造函数构造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

答案 1 :(得分:0)

首先考虑输入参数:

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 ...
}

鉴于您需要参数字符串的副本移动不是一个选项。你不能只是让第二个字符串等于第一个字符串。 std::string赋值运算符具有创建最有效副本所需的所有信息。

我不知道您的其他任何解决方案如何能够改善这一点。