C++ 为什么我们需要配对<;迭代器,bool>;插入(值类型和值);std::set'的版本;s插入函数

C++ 为什么我们需要配对<;迭代器,bool>;插入(值类型和值);std::set'的版本;s插入函数,c++,c++11,rvalue-reference,C++,C++11,Rvalue Reference,嗨,我想了解如何使用带有右值和左值引用的函数的重载版本作为参数。因此,这是我为更好地理解差异而编写的示例: car.h class Car{ private: int number=1000; string name="default name"; std::set<int> Carset; public: void pushtoset(int &); void pushtos

嗨,我想了解如何使用带有右值和左值引用的函数的重载版本作为参数。因此,这是我为更好地理解差异而编写的示例:

car.h

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

}
main.cpp

#include "car.h"

void Car::pushtocar(int &x){

    Carset.insert(x);
}
void Car::pushtocar(int &&x){
    Carset.insert(x);    
}
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)在版本II中x是否会被复制或移动?我想它会被复制的。因此,如果x被复制,那么如果x被破坏就没有问题了,因为插入的元素和x是相互独立的。但是现在如果我写
Carset.insert(std::move(x))则x将“移动”到集合中,而不是复制。在这种情况下,我们将遇到问题,函数体完成后,x将被销毁,因此插入的元素也将被销毁。是否有任何方法可以防止在移动的情况下插入到集合中的元素使x处于有效状态而被销毁?我对这个概念的理解是否正确?

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

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

    Carset.insert(x);
}

。因此,当您调用
.insert
时,对象将被复制到容器中。
std::set
将拥有其对象。因此,对象的生命线与容器无关,因为它是复制的。我想它应该能回答你的两个问题。

移动
int
只是一个副本。。。使用
std::string
而不是
int
将使示例更有意义。“x将被销毁,因此插入的元素也将被销毁。”移动不是这样工作的。但是.insert()可以采用左值和右值引用参数。当我像
Carset.insert(std::move(x))那样调用它时则应使用右值引用版本。也就是说,应该移动而不是复制该值。当x超出范围时,它将被摧毁。但是我们在集合中插入(移动)了值。从那里它也会被销毁吗?访问x是未定义的行为,因为它被容器内部生成的值交换。我们不知道x将取哪个值,也不确定这是如何在VLQ队列中结束的。这不是VLQ,只是错了(这是下行投票的目的)。但是.insert()可以接受左值和右值引用参数。当我像
Carset.insert(std::move(x))那样调用它时则应使用右值引用版本。也就是说,应该移动而不是复制该值。当x超出范围时,它将被摧毁。但是我们在集合中插入(移动)了值。它也将从那里被销毁吗?@JasonLiam,
std::set
中的构造函数将处理它,以便插入对象时,
x
将处于可销毁状态(对其以前拥有的右值引用没有影响)。当
x
超出范围时,它不再指向该值。此外,它应该与容器的用户无关,
std::set
使用、复制或移动什么(如果只是出于好奇)。是的,这正是我要问的。如何使x保持有效状态。因为当我使用
std::move(x)
x将不再可用(除了分配或销毁它)。std::set构造函数如何使x保持有效状态。?即使在std::move(x)之后,std::set的构造函数是如何使用x的?@JasonLiam,你没有试过代码吗?它应该按原样工作,因为容器处理从对象移动的状态。是的,我已经试过了。这只是我给出的一个示例。实际项目要大得多,跨越20-30个文件(包括接口和实现文件)。我很好奇
.insert(std::move(x))中到底发生了什么案例。同样,我应该在II版本
的主体中使用以下哪一项
。插入(x)
以及为什么?它们完全相等吗?