【问题标题】:Why do we need pair<iterator,bool> insert (value_type&& val); version of std::set's insert function为什么我们需要pair<iterator,bool> insert (value_type&& val); std::set 的插入函数的版本
【发布时间】:2021-08-12 13:19:35
【问题描述】:

您好,我想了解如何使用带有右值和左值引用作为参数的函数的重载版本。所以这是我写的例子,以更好地理解差异:

car.h

class Car{
    private:
      int number=1000;
      string name="default name";
      std::set<int> Carset;
    public:
       void pushtoset(int &);
       void pushtoset(int &&);

}

car.cpp

#include "car.h"

void Car::pushtocar(int &x){

    Carset.insert(x);
}
void Car::pushtocar(int &&x){
    Carset.insert(x);    
}

ma​​in.cpp

int main(){
    Car object;
    int x = 43;    
object.pushtocar(x); //this calls pushtocar(int&) version(say version I)
object.pushtocar(54); // this calls pushtocar(int &&) version(say version II)
    return 0;

我的问题是在版本 II 的情况下,当这个成员函数的主体完成时,由于在函数主体内参数 x 是一个左值(它是函数的本地值),x 将被销毁。这是否意味着我们在集合中插入的值也将被销毁?如果是这样,我怎样才能防止推到集合上的值不被破坏?我认为与第一个有关的第二个问题是,当我在第二版中写Carset.insert(x); 时,x 会被复制或移动吗?我认为它会被复制。所以如果 x 被复制,那么如果 x 被破坏就没有问题,因为插入的元素和 x 是相互独立的。但是现在如果我写Carset.insert(std::move(x));,那么 x 将被“移动”到集合而不是复制。所以在这种情况下,我们会遇到函数体完成后的问题,x 将被销毁,因此插入的元素也将被销毁。有什么方法可以防止在这个移动的情况下插入集合中的元素,即让 x 处于有效状态以被销毁?我对这个概念的理解是否正确?

【问题讨论】:

  • 移动int 只是一个副本...使用std::string 而不是int 将使示例更有意义。
  • "x 将被销毁,因此插入的元素也将被销毁。" 这不是移动的工作原理。

标签: c++ c++11 rvalue-reference


【解决方案1】:

版本 II 采用 'swap' [std::move] 所以完成后,传递给函数的参数是未定义的。你不能再使用它了。右值引用延长了对象的生命周期,它不会被立即销毁。 我采用左值的版本,所以它是复制构造函数。它的正确形式应该是

void Car::pushtocar(const int &x){

    Carset.insert(x);
}

【讨论】:

  • 但是 .insert() 可以采用左值和右值引用参数。当我把它称为Carset.insert(std::move(x)); 时,应该使用右值参考版本。那就是应该移动而不是复制值。 cplusplus.com/reference/set/set/insert 当 x 超出范围时,它将被销毁。但是我们将值插入(移动)到集合中。它也会从那里被摧毁吗?
  • 访问 x 是未定义的行为,因为它被容器内部生成的值所交换。我们不知道 x 会取哪个值
  • 不确定它是如何进入 VLQ 队列的。这不是 VLQ,只是错了(这就是反对票的原因)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-25
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
相关资源
最近更新 更多