为什么我们不能使用 move 语义只适用于按值传递而不适用于 const 左值引用?

Why can we not use move semantics only apply for pass-by-value and not const lvalue reference?

Here is the article I am using as a reference, which was ultimately mentioned in 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;
}

然后说:

Although sorted and sorted2 seem at first to be identical, there could be a huge performance difference if a compiler does copy elision. Even if the actual argument to sorted2 is an rvalue, the source of the copy, names, is an lvalue, so the copy can’t be optimized away. In a sense, copy elision is a victim of the separate compilation model: inside the body of sorted2, there’s no information about whether the actual argument to the function is an rvalue; outside, at the call site, there’s no indication that a copy of the argument will eventually be made.

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

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

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


since get_names() is a rvalue, we can use move semantics.

不总是。考虑何时调用移动构造函数。

However if the parameter is a const lvalue reference, then we must "preserve" the value as an lvalue, so a simple switch of pointers cannot occur

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

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 左值引用可以绑定右值。但是,您无法修改对象,因此不会发生简单的指针切换。