其他分享
首页 > 其他分享> > c – vector :: push_back和std :: move [复制]

c – vector :: push_back和std :: move [复制]

作者:互联网

参见英文答案 > What does auto&& tell us?                                    4个
我尝试了以下代码:

#include <iostream>

struct test{
    test(){}
    test(test const &){
        std::cout<<__LINE__<<"\n";
    }
    test(test&&){
        std::cout<<__LINE__<<"\n";
    }
};

#include <vector>
#include <utility> // std::move
int main(){
    auto&& tmp = test();
    std::vector<test> v;
    v.push_back(tmp);
    std::cout<<__LINE__<<"\n";
    v.push_back(std::move(tmp));

    return 0;
}

vs2013编译器输出:

6 //复制

18

9 //移动

9 //移动

g和clang输出:

6 //复制

18

9 //移动

6 //复制

我的问题是:

>是tmp测试类型&&? tmp是左值吗?
>如果tmp的类型是test&&,为什么第一个push_back不使用移动构造函数?
>最后一个输出来自哪里?为什么vs2013和g输出不同的结果?

谢谢.

回答第3个问题:
它来自andrew.punnett评论的重新分配.

解决方法:

Is the type of tmp test&&?

是的,不是. tmp是test&&类型的右值引用变量,但作为表达式的标识符tmp具有类型test和值类别lvalue. &永远不是表达式的一部分.

Is tmp a rvalue?

否.对标识符的任何使用都是左值表达式,甚至是右值引用的名称. Rvalue引用变量的访问基本上与左值引用变量相同;只有decltype(tmp)可以区分. (通常你会使用decltype((tmp))来避免分辨.)

If the type of tmp is test&&, why didn’t the first push_back use move constructor?

因为右值引用的名称仍然是左值.要获得rvalue表达式,请使用move(tmp).

Where did the last output come from? Why did vs2013 and g++ output different results?

默认情况下,Clang和GCC仅为向量中的一个对象腾出空间.添加第二个对象时,会重新分配矢量存储,从而导致复制对象.他们为什么不感动?因为移动构造函数不是noexcept,所以如果它抛出异常,则无法撤消重新分配.

至于MSVC的两个动作,有两种可能性,你可以通过实验来区分 – 我没有副本方便.

>默认情况下,MSVC在向量内为两个对象保留了足够的空间.第二步是来自内部局部变量.
> MSVC忽略了移动构造函数为noexcept并将其调用以执行重定位的要求.这将是一个错误,但在这种情况下,它掩盖了一个常见的错误.

如果用deque替换vector,则不会再看到副本,因为deque不允许假定可复制性.

标签:rvalue,c,c11,move
来源: https://codeday.me/bug/20190825/1716848.html