"想要速度?通过价值"是多么真实

iam*_*nka 45 c++ c++11

如我错了请纠正我.说我有:

struct X
{
    std::string mem_name;

    X(std::string name)
        : mem_name(std::move(name)) 
    {}
    ...
};
struct Y
{
    std::string mem_name;

    Y(const std::string &name)
        : mem_name(name) 
    {}
    ...
};
Run Code Online (Sandbox Code Playgroud)

Xctor中,name显然是传递给任何参数的副本X,X调用std::string初始化的移动mem_name,对吧?

让我们称之为X*复制然后移动 ; 两个操作:COPY,MOVE.

Y's ctor中,name是一个const ref,这意味着没有元素的实际副本,因为我们直接处理从Y需要创建对象的地方传递的参数.但是,我们复制name到初始化mem_nameY; 一个操作:COPY.因此它应该更快(对我来说更好)?

在Scott Meyer的GN13演讲中(围绕时间框架8:10和8:56),他谈到了"想要速度?通过价值传递",我想知道在传递参数时是否有任何性能差异或损失(或者字符串是准确的)通过引用和传递值"以获得速度?"

我知道按值传递参数可能很昂贵,特别是在处理大数据时.

也许(显然?)我的谈话中缺少一些东西?

Rei*_*ica 57

"想要速度?通过价值" (1)的想法是,有时,副本可以省略.上课,XY考虑这个用例:

// Simulating a complex operation returning a temporary:
std::string foo() { return "a" + std::string("b"); }


struct X
{
  std::string mem_name;
  X(std::string name): mem_name(std::move(name)) {}
};

struct Y
{
  std::string mem_name;
  Y(const std::string &name): mem_name(name) {}
};


int main()
{
  X(foo());
  Y(foo());
}
Run Code Online (Sandbox Code Playgroud)

现在让我们分析一下构造案例.

X第一.foo()返回一个临时的,用于初始化对象name.然后将该对象移入mem_name.请注意,编译器可以应用返回值优化并直接在空间中构造返回值foo()(实际上甚至是返回值operator+).因此,实际上不会发生复制,只是一次移动.name

现在让我们来分析吧Y.foo()再次返回一个临时的,绑定到引用name.现在返回值没有"外部提供的"空间,因此必须在自己的空间中构造并绑定到引用.然后将其复制到mem_name.所以我们正在做一个副本,没有办法解决它.

简而言之,结果是:

  • 如果左值被传入,都XY将执行复制(X初始化时name,Y初始化时mem_name).此外,X将执行移动(初始化时mem_name).

  • 如果传入右值,X则可能只执行移动,而Y必须执行复制.

通常,移动预期是一种操作,其时间要求与传递指针(通过引用传递的内容)相当.因此,实际上,X并不比Y左值更差,对于右值更好.

当然,这不是一个绝对的规则,必须采取一些盐.如有疑问,请查看.


(1)该链接容易暂时不可用,并且从2014年12月12日起,它似乎被打破(404).几个博客网站上似乎提供了内容的副本(尽管有奇怪的格式):

或者,可以通过返回机器访问原始内容.

另请注意,该主题总体上激起了相当多的讨论.谷歌搜索文章标题带来了很多后续和反点.为了列举其中一个例子,SO成员juanchopanza"想要速度吗?不要(总是)超值"

  • @jerry_fuyi 答案中的代码不处理在某处传递“X”或“Y”,它处理在某处传递“std::string”。当然,[重载 `const std::string&` 和 `std::string&&`](http://coliru.stacked-crooked.com/a/4c4b7fdd0bb7a53e) 将是最安全、最有效的做法,但是这是额外的代码,如果你的函数有更多这样的参数,它会以组合方式爆炸。这个想法是,取值函数的工作原理几乎与左值+右值重载对一样好。 (3认同)
  • 现在找到一个新的链接404它会很棒. (2认同)

cdm*_*dmh 14

优化没有一般规则.按值传递可以在C++ 11中获得一些大的胜利,包括移动语义和复制省略.

如果你真的想要的速度,简介您的代码.