C++;11移动语义vs C++;98 我研究了C++ 11移动语义,我有这样的问题。p>

C++;11移动语义vs C++;98 我研究了C++ 11移动语义,我有这样的问题。p>,c++,move,move-semantics,C++,Move,Move Semantics,例如: 如果我们有 vector<T> vt; // also assume that T have pointers on data in separate memory vt.push_back(...); 据我所知,移动语义几乎就是这样做的(但将a保持在某种一致的状态)。因此,我认为我们实际上有能力实现旧C++中的移动。是吗 同样,我们也可以在上一个例子中对vector执行相同的操作,“Move semantics”为编译器提供了一种方法来传递对构造函数之类的引用,这些构造函

例如:

如果我们有

vector<T> vt; // also assume that T have pointers on data in separate memory
vt.push_back(...);
据我所知,移动语义几乎就是这样做的(但将a保持在某种一致的状态)。因此,我认为我们实际上有能力实现旧C++中的移动。是吗

同样,我们也可以在上一个例子中对vector执行相同的操作,“Move semantics”为编译器提供了一种方法来传递对构造函数之类的引用,这些构造函数可以区分为左值引用(在C++98中找到的您习惯的类型)和右值引用(C++11新增,使用
&&
表示法,它们指的是临时和中间的对象,可能不会超过当前语句)

所以现在我们可以编写一个复制构造函数(“使新对象成为此对象的副本”)和一个不同的移动构造函数(“使新对象成为此对象的副本,顺便说一下,源对象是一个临时对象,下一步将被销毁,因此如果您希望以不使源对象保持完整的方式进行优化,请继续”)

例如,在一个容器类中,您可以使用copy构造函数复制容器类,新的副本将包含其所有内容的完整副本(这意味着将发生类似于内容的逐元素复制构造的事情)。但是移动构造函数可以跳过所有这些工作,只需与源容器交换内部构件,只需接管源容器的内容并将源容器保留为空。(稍后源容器被销毁,这应该很简单,因为它是空的。)这通常可以在恒定时间内完成,而不是O(N)或者更糟

在C++98中,你不能像构造函数那样做(因此也不能像临时对象那样),因为它只知道如何制作副本。有一种方法可以通过
swap()
函数(以及某些类中的方法)实现类似的效果,但必须显式编写。(基本上,要将容器
a
的内容移动到新构造的空容器
b
,您可以调用
swap(a,b);
,然后销毁
a
,然后将其清空。)


在C++98中,一个无法正确操作的示例是使用返回向量的函数的结果初始化向量:

vector<int> fibonacci(int n) { 
    vector<int> result;
    if(n <= 0) return result;
    result.push_back(0);
    if(n <= 1) return result;
    result.push_back(1);
    for(int i = 1; i < n; ++i)
        result.push_back(result[i] + result[i - 1]);
    return result; 
}

vector<int> datavect = fibonacci(10);
向量斐波那契(int n){ 矢量结果;
如果(n)我想你是误解移动语义…这里没有什么区别C++ 11和C++ 98因为这里的指针只是指针复制的。还有一个<代码>向量(代码< >代码> >指针只会在指针周围移动,指针从来没有指向。当然,C++ 98会调用一个深层拷贝,所以它是Wi。不仅指针,而且指针指向的所有数据都是复制的,所以问题是为什么我们不能用C++实现移动语义?98@Nikita不,c++98不会自动执行深度复制。它只会复制指针值,就像c++11一样。这:解释了为什么
auto_ptr
不起作用。是的,移动语义就是这样做的。所以我的问题是是如何(或为什么不)在C++ 98中不能实现移动语义?参见我的最后一段。简而言之:你必须手动完成,在某些情况下,比如返回函数的容器(与指针或引用相反),根本不能这么做。是的,我同意在交换和斐波那契的情况下,旧C++是不合适的。但是在我的例子中(还有vector)通过模拟移动语义可以提高性能。那么为什么在C++11之前他们没有在stl中实现它呢?@Nikita问题不在于stl,而在于用户定义的类型。你需要有这种奇怪的行为(copy==资源传输)适用于需要此优化的所有值类型的容器。本质上类似于
std::auto_ptr
。但是,这打破了通常的复制语义,其中复制(按照约定)表示深度复制。因此,您可以在容器中使用此类类型作为值类型,但不能在容器外部使用相同的类型。您可以更改STL并引入新的ctor,如
a(a&,transfer\u resource\t)
,但这不会自然地与右值一起工作。
vector<int> fibonacci(int n) { 
    vector<int> result;
    if(n <= 0) return result;
    result.push_back(0);
    if(n <= 1) return result;
    result.push_back(1);
    for(int i = 1; i < n; ++i)
        result.push_back(result[i] + result[i - 1]);
    return result; 
}

vector<int> datavect = fibonacci(10);