【问题标题】:Why can we not use move semantics only apply for pass-by-value and not const lvalue reference?为什么我们不能使用 move 语义只适用于 pass-by-value 而不是 const lvalue 引用?
【发布时间】:2019-10-13 03:51:18
【问题描述】:

Here是我作为参考的文章,最终在this SO answer中提到。

作者举了两个例子:

示例 1:

std::vector<std::string> 
sorted(std::vector<std::string> names)
{
    std::sort(names);
    return names;
}

// names is an lvalue; a copy is required so we don't modify names
std::vector<std::string> sorted_names1 = sorted( names );

// get_names() is an rvalue expression; we can omit the copy!
std::vector<std::string> sorted_names2 = sorted( get_names() );

示例 2:

std::vector<std::string> 
sorted2(std::vector<std::string> const& names) // names passed by reference
{
    std::vector<std::string> r(names);        // and explicitly copied
    std::sort(r);
    return r;
}

然后说:

虽然 sorted 和 sorted2 乍一看似乎是相同的,但可以 如果编译器确实复制省略,则性能差异很大。甚至 如果 sorted2 的实际参数是右值,则 copy, names, 是一个左值,所以拷贝不能被优化掉。在一个 从某种意义上说,复制省略是分离编译模型的牺牲品: 在 sorted2 的主体中,没有关于是否 函数的实际参数是一个右值;外面,打电话 网站,没有迹象表明该论点的副本将 最终完成。

我的问题很简单: 为什么编译器在第二个示例中不能使用复制省略,而在第一个示例中可以?

如何通过值传递和引用来区分它们? names 在两个实例中都被命名,所以我假设我们也在两个实例中创建了一个左值。

【问题讨论】:

    标签: c++ move-semantics rvalue


    【解决方案1】:

    区别在于names是否可以修改对象。 const 左值引用不可修改。


    由于 get_names() 是一个右值,我们可以使用移动语义。

    并非总是如此。考虑何时调用移动构造函数。

    但是,如果参数是 const 左值引用,那么我们必须将值“保留”为左值,因此不能发生简单的指针切换

    当参数为左值引用时,可以修改对象。但是,您不能传递右值。

    std::vector<std::string> 
    sorted3(std::vector<std::string>& names)
    {
        std::sort(names);
        return names;
    }
    
    // names is an lvalue; lvalue reference can bind lvalue. argument will be modified after execution `sorted3`.
    std::vector<std::string> sorted_names1 = sorted3( names );
    
    // get_names() is an rvalue expression; we cannot bind by lvalue reference.
    //std::vector<std::string> sorted_names2 = sorted3( get_names() );
    

    const 左值引用可以绑定右值。但是,您不能修改该对象,从而不会发生简单的指针切换。

    【讨论】:

    • 所以如果我们考虑vector&lt;string&gt; names = sorted( get_names () ),因为get_names()是一个右值,我们可以使用移动语义。但是,如果参数是const 左值引用,那么我们必须将右值“保留”为左值,这样就不会发生简单的指针切换,对吗?但是当我们按值传递时,就不需要保存了,对吗?抱歉,我对此很陌生,所以一些细节会让事情更清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 2019-11-17
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多