我正在尝试编写一个有效的方法来将Image(一个QImage - Qt5.3)分配给我班级的成员变量:
void ImageView::setImage(QImage&& image){
std::cout << &image << std::endl;
_image = image;
//_image = std::move(image);
std::cout << &_image << std::endl;
_imageAssigned = true;
updateResizedImage();
update();
}
我可以使用两行代码,第一行是_image = image;
,第二行是_image = std::move(image);
。现在我认为第一行应该是完全正常的,并且实际上应该使用QImage的=运算符重载,它采用右值引用,因为图像已经是右值引用。但是,Visual Studio的工具提示向我显示使用了normal =运算符。如果我改为使用第二行,工具提示会显示使用右值的重载。现在我的问题是为什么会这样。我的第一行还不够吗?调用已经是右值参考的变量的移动对我来说似乎是超级的。
我尝试通过输出指针来自己测试(如代码中所示)。现在,无论我使用哪一行,指针都是不同的。这让我感到困惑。看来,我的代码并没有像我想象的那样运行。谁能告诉我我做错了什么?
感谢您的帮助
答案 0 :(得分:4)
具有名称的对象是左值。声明为QImage&&
表示只有一个右值可以绑定到此引用,但引用本身始终是左值:它有一个名称。如果要转发实体的右值,则必须使用std::move()
明确指出。如果推导出右值(即,您使用T&&
形式的推导模板参数,其中T
为模板参数),您将使用std::forward<T>(arg)
有条件地转发右值。
image
和_image
的地址当然是不同的,因为它们首先是不同的对象。如果QImage
包含具有地址的对象,则可以验证是否使用该地址移动了对象。例如,如果您使用std::vector<T>
而不是QImage
,则可以使用类似的内容来确定数组是否已被移动:
void f(std::vector<T>&& v) {
std::cout << (v.empty()? 0: v.data()) << '\n';
std::vector<T> other;
other = v; // will be copied
std::cout << (other.empty()? 0: v.data()) << '\n';
other = std::move(v); // will be moved
std::cout << (other.empty()? 0: v.data()) << '\n';
}