我想使用C ++ 11移动语义。我写了下面的课:
class ColorM
{
public:
ColorM(float _r, float _g, float _b, float _a){
qDebug()<<"Constructor";
r = _r;
g = _g;
b = _b;
a = _a;
m = new float[16];
}
ColorM(const ColorM &other){
qDebug()<<"Copy Constructor";
}
~ColorM(){
if (m != nullptr)
{
qDebug()<<"Deleting resource.";
// Delete the resource.
delete[] m;
}
}
// Move constructor.
ColorM(ColorM&& other)
{
qDebug()<<"Move Constructor";
r = other.r;
g = other.g;
b = other.b;
a = other.a;
m = other.m;
other.m = nullptr;
}
float r;
float g;
float b;
float a;
float *m;
private:
};
当我尝试:
std::vector<ColorM> vec;
vec.push_back(ColorM(0.1, 0.6, 0.3, 0.7));
vec.push_back(ColorM(0.2, 0.6, 0.3, 0.7));
vec.push_back(ColorM(0.3, 0.6, 0.3, 0.7));
我有复制构造函数调用。我做错了什么? 我以this为例。并用g ++编译它。
以下是我用于测试的QT项目:http://wikisend.com/download/261514/MoveConstructor.zip
答案 0 :(得分:1)
您可以使用std::vector<T>::emplace_back
功能
std::vector<ColorM> vec;
vec.emplace_back(0.1, 0.6, 0.3, 0.7); // Will call
vec.emplace_back(0.2, 0.6, 0.3, 0.7); // ColorM::ColorM(float _r, float _g, ..) ctor
vec.emplace_back(0.3, 0.6, 0.3, 0.7);
或(使用ColorM
移动构造函数)
std::vector<ColorM> vec;
vec.emplace_back(ColorM(0.1, 0.6, 0.3, 0.7)); // Should be equivalent to your code
vec.emplace_back(ColorM(0.2, 0.6, 0.3, 0.7));
vec.emplace_back(ColorM(0.3, 0.6, 0.3, 0.7));
注意:我不同意user2485710
的回答。由于ColorM(0.1, 0.6, 0.3, 0.7)
的{{1}}参数是临时的,我希望编译器将其识别为r值引用并使用{{1}应用移动构造函数而不使用 },自push_back
has an overload for r-value references。
换句话说,std::move
取push_back
个对象应避免使用emplace_back
之类的副本;在ColorM
的情况下,您必须在适当的位置构建。
使用上面的第二个版本,与push_back
相比,您应该获得更好的诊断消息,即在编译时失败而不是复制构造函数的这种微妙的意外使用。
答案 1 :(得分:0)
这是因为你的构造函数的签名和你push_back()
操作的参数。
简而言之T()
生成类型为T
的对象的新实例,如果此实例与标签/变量无关,则实例仍然是unnamed
,但是他没有不改变它自己的类型,它始终是T
类型的“某种东西”(它甚至可以被视为T&
或const T&
但这不是本主题的参数。)
要获得T&&
至cast
所需的T&&
签名,并且在C ++ 11中,这是std::move
的工作,这也是一种无条件的演员,所以在任何地方都很容易使用。
您可以将std::move
添加到您班级内的构建工具或push_back
的通话中。