在std :: move'ing时警告调用copy ctor

时间:2017-01-31 16:11:58

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

给定一个程序:

#include <iostream>
#include <vector>

using namespace std;

struct Vec {
    Vec() = default;

    Vec(const Vec& vec) 
        : v_(vec.v_)
    {
        cout << "copy Vec" << endl;
    }

    Vec(Vec&& vec)
        : v_(std::move(vec.v_))
    {
        cout << "move Vec" << endl;
    }

    vector<double> v_{};
};

struct T1 {
    Vec Value;
};

struct T2 {
    T2(const T1& t1) 
        : Value(std::move(t1.Value))
    {

    }

    Vec Value;
};

struct T3 {
    T3(T1&& t1)
        : Value(std::move(t1.Value))
    {

    }

    Vec Value;
};

int main() {
    T1 t1;

    T2 t2{ t1 };

    T3 t3{ std::move(t1) };

    return 0;
}

输出:

copy Vec
move Vec

在这两种情况下,我std::move正在t1.ValueVec ctor。

是否有可能在Clang(或其他编译器)中启用某些警告,因此它警告我移动实际上调用了复制构造函数?

(例如,当我从函数返回std::unique_ptr std::move(result)时,Clang已经可以警告性能问题了。)

1 个答案:

答案 0 :(得分:1)

  

是否有可能在Clang(或其他编译器)中启用某些警告,因此它警告我移动实际上调用了复制构造函数?

移动过程与专门调用std::move无关。这只是演员。调用移动构造函数/赋值运算符时会发生移动。移动可以在不调用std::move的情况下发生(例如,编译器警告您的情况),并且正如您所看到的那样,即使您使用std::move也不会发生移动。

您无法从const引用移动,因为......它是 const 。运动具有破坏性,因此需要能够修改物体。哪个const不允许。

运动最终是一种优化的复制操作。因此,执行复制而不是移动通常是可以的,特别是如果类型没有移动构造函数。

如果您愿意,您可以编写自己的std::movestatic_assert T不是const

template< class T >
constexpr typename std::remove_reference<T>::type&& my_move( T&& t )
{
    static_assert(!std::is_const<T>::value, "Cannot move from a const reference");
    return static_cast<typename std::remove_reference<T>::type&&>(t);
}