为什么移动比通过const&?更昂贵?

时间:2016-10-05 02:23:29

标签: c++ assembly move copy-constructor lifetime

我在生命结束之前将一些对象传递给构造函数。

int main(){

    //I wanted to avoid short string optimization in this example.
    const std::string a(25,"a");
    const std::string b(25,"b");
    const std::string c(25,"c");

    Foo f{a,b,c};
}

我为Foo的构造函数考虑了两个选项。

const&(调用字符串' s复制构造函数):

Foo(const std::string & a,
    const std::string & b,
    const std::string & c)
:a(a)
,b(b)
,c(c)
{}

std::move(调用字符串'移动构造函数):

Foo(std::string a,
    std::string b,
    std::string c)
:a(std::move(a))
,b(std::move(b))
,c(std::move(c))
{}  

-01gcc 7,我得到了以下结果:

+-------------+-----------------------+
| constructor | assembly instructions |
+-------------+-----------------------+
| const&      |                   192 |
| move        |                   264 |
+-------------+-----------------------+

为什么const&指示较少?
我认为移动比通过复制构造函数创建新字符串便宜。

将变量作为构造函数参数传递的经验法则是什么 当这些论点的生命周期结束时?

2 个答案:

答案 0 :(得分:5)

您没有调用移动构造函数。你的参数字符串是const。因此,当您对它们使用std::move时,结果为const std::string&&。这并没有调用移动构造函数,其签名需要std::string&&

答案 1 :(得分:0)

如果编译器没有为main调用构造函数的特殊版本,那么main仍在调用带有签名Foo(std::string a, std::string b, std::string c);的函数

除非它内联,否则gcc会对其进行克隆,实际上以不同的方式传递args,函数的定义中的代码不能改变它的调用方式。< / p>

想象一下构造函数定义是在一个单独的文件中,并且在编译main时甚至不可见,只有原型。这类似于仅使用-O1进行编译所获得的。