【问题标题】:How do I know if I'm using copy or move?我如何知道我使用的是复制还是移动?
【发布时间】:2016-10-07 03:59:43
【问题描述】:

我理解 C++14 标准库使用移动语义是否正确?换句话说,我是否可以确信我在以下程序中使用的是移动而不是副本:

#include <iostream>
#include <string>
#include <vector>

using namespace std::string_literals;

std::vector<std::string> greeting()
{
    std::vector<std::string> vs {"hello"s, "world"s};
    return vs;
}

int main()
{
    std::vector<std::string> s = greeting();
    std::cout << s[0] << " " << s[1] << "\n" ;
}

有什么方法可以检查吗?

下面的例子怎么样:

#include <iostream>
#include <string>
#include <vector>

using namespace std::string_literals;

class Greeting {
    public:
    std::string first, second;
    Greeting() { first = "hello"s ; second = "world"s ;};
};

Greeting greetingc()
{
    Greeting g;
    return g;
}

int main()
{
    Greeting g = greetingc();
    std::cout << g.first << " " << g.second << "\n" ;
}

移动还是复制?

【问题讨论】:

  • 您到底想检查哪里?哪行代码应该是一个动作?
  • @rubenvb 我的意思是当从greeting(0或greetingc()中的任何一个调用return语句时,程序会做什么:它是复制对象(一个潜在的昂贵操作)还是它移动对象(廉价操作)。
  • 一般来说,无论何时创建临时对象,但您无权访问,都适合使用 move semantics
  • 可能是related

标签: c++ c++14 move-semantics


【解决方案1】:

在大多数情况下,复制和移动之间没有太大区别。仅当您拥有不想复制的东西的所有权时,这才有趣。就像分配给对象的套接字或内存一样。因此,只有当某些东西既昂贵时(例如,当您只需要其中一个时复制一大块内存)并且您必须照顾所有权(没有两个指针指向同一内存或套接字等时)才有趣。 .)。

在您的两个示例中,最有可能发生的是编译器将执行 RVO 返回值优化,这消除了复制或移动的需要。 Vector 定义了 move,因此编译器将尽可能使用 move 语义(右值语义),并且您可以使用 std::move 强制它。但是因为它,你的例子中的任何一个都会更快。 Read more about move.

如果你很好奇,你可以实现复制和移动,并将它们写入控制台。

Greeting(const Greeting& g)
{
    std::cout << "Copy";
    // Copy it
}

Greeting(Greeting&& g)
{
    std::cout << "Move";
    // Move it
}

通常会发生这种情况。

Greeting foo(){ Greeing a; return a; }
Greeting a; // Normal construction
Greeting b(a); // Copy of 'a'
Greeting c(std::move(a)); // Move, 'a' will be changed
Greeting d(foo()); // Move from rvalue which is returned from foo() unless RVO kicks in

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多