2016-06-07 128 views
4

我是否理解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" ; 
} 

移动或复制?

+0

你究竟在哪里检查?什么行代码应该是一个举动? – rubenvb

+0

@rubenvb我的意思是,当从greeting(0或greetingc())中调用return语句时,程序会做什么:它是复制对象(可能是一个昂贵的操作)还是它移动对象(便宜的操作)。 – blippy

+0

一般而言,无论何时创建临时对象,您无权访问该对象,都可以成为“移动语义”的良好选择。 – sameerkn

回答

2

在大多数情况下,复制和移动之间没有太大的区别。只有拥有所有权才能让你不想复制的东西变得有趣。就像分配给对象的套接字或内存一样。所以,只有当一些东西都很昂贵时才有意思(比如当你只需要其中一个时就复制一大块内存),而且你必须关心所有权(不要有两个指针指向同一个内存,或者一个套接字等等。 )。

在这两个示例中,最有可能发生的情况是编译器将执行RVO返回值优化,从而消除复制或移动的需要。 Vector定义移动,以便编译器在可能时使用移动语义(右值语义),并且可以用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