【问题标题】:Assigning rvalue reference to member variable将右值引用分配给成员变量
【发布时间】:2023-03-04 00:08:01
【问题描述】:

我正在尝试编写一种有效的方法来将图像(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 的 =operator 重载,它采用右值引用,因为 image 已经是一个右值引用。但是,Visual Studio 的工具提示显示使用了普通的 = 运算符。如果我改用第二行,工具提示会显示使用右值的重载。现在我的问题是为什么会这样。第一行还不够吗?对已经是右值引用的变量调用 move 对我来说似乎是多余的。

我尝试通过输出指针来测试自己(如代码中所示)。现在,无论我使用哪条线,指针都是不同的。这让我感到困惑。看起来,我的代码并没有像我想象的那样工作。谁能告诉我我做错了什么?

感谢您的帮助

【问题讨论】:

    标签: c++ visual-studio qt rvalue-reference


    【解决方案1】:

    一个有名字的对象是一个左值。 QImage&amp;&amp; 的声明表明只能将右值绑定到此引用,但引用本身始终是左值:它有一个名称。如果你想转发一个实体的右值,你必须明确地使用std::move()。如果推导出右值(即,您使用T&amp;&amp; 形式的推导模板参数,其中T 是模板参数),您将使用std::forward&lt;T&gt;(arg) 有条件地转发右值。

    image 和_image 的地址当然是不同的,因为它们首先是不同的对象。如果QImage 包含一个带有地址的对象,您可以验证该对象是否是使用该地址移动的。例如,如果您使用 std::vector&lt;T&gt; 而不是 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';
    }
    

    【讨论】:

    • 感谢您的回答!我现在有点理解,只要我们在函数内部,右值基本上就变成了一个普通变量(尽管是一个引用)。区别仅存在于调用哪个函数(采用普通引用或采用右值引用的函数,对吗?)。我还能够通过将指针更改为std::cout &lt;&lt; (void*)image.bits() &lt;&lt; std::endl; 来输出指针。这样,如果我使用移动,指针地址是相等的,如果我不使用,指针地址是不相等的。
    猜你喜欢
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    相关资源
    最近更新 更多