C++11 右值和 move 语义混淆(return 语句)

标签 c++ c++11 move-semantics rvalue-reference c++-faq

我正在尝试理解右值引用并 move C++11 的语义。

这些例子有什么区别,哪些不做 vector 拷贝?

第一个例子

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> &&rval_ref = return_vector();

第二个例子

std::vector<int>&& return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

第三个例子

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

最佳答案

第一个例子

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> &&rval_ref = return_vector();

第一个示例返回一个由 rval_ref 捕获的临时值。该临时文件的生命周期将超出 rval_ref 定义,您可以使用它,就好像您已经按值(value)捕获了它一样。这与以下内容非常相似:

const std::vector<int>& rval_ref = return_vector();

除了在我的重写中你显然不能以非常量方式使用 rval_ref

第二个例子

std::vector<int>&& return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

在第二个示例中,您创建了一个运行时错误。 rval_ref 现在包含对函数内部已破坏的 tmp 的引用。运气好的话,这段代码会立即崩溃。

第三个例子

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return std::move(tmp);
}

std::vector<int> &&rval_ref = return_vector();

您的第三个示例与您的第一个示例大致相同。 tmp 上的 std::move 是不必要的,实际上可能是性能悲观,因为它会抑制返回值优化。

编写代码的最佳方式是:

最佳实践

std::vector<int> return_vector(void)
{
    std::vector<int> tmp {1,2,3,4,5};
    return tmp;
}

std::vector<int> rval_ref = return_vector();

即就像在 C++03 中一样。 tmp 在 return 语句中被隐式视为右值。它将通过返回值优化(不复制,不 move )返回,或者如果编译器决定它不能执行 RVO,那么它 will use vector's move constructor to do the return .仅当不执行 RVO,并且返回的类型没有 move 构造函数时,才会使用复制构造函数进行返回。

关于C++11 右值和 move 语义混淆(return 语句),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4986673/

相关文章:

c++ - decltype 和左值表达式

c++ - 为什么 std::move 对 std::unique_lock 没有任何影响?

c++ - 通过 Opencv 和 tesseract-ocr 从分数框中识别分数

c++ - 返回函数指针的函数签名

c++ - 这个尾随返回类型在 C++11 中合法吗?

c++ - 可以将 std::pairs 的 std::vector 转换为字节数组吗?

c++ - move 分配和引用成员

c++ - 在每个不提供用户定义的 move 构造函数的类中显式声明默认的 move 构造函数是一种好习惯吗?

c++ - 在 g++ 编译器中使用 strlen 获取数组的长度

c++ - 如何为 OS X Yosemite 安装 Eclipse for C++?