• 关于vector存放对象和对象指针的探索


    1 vector容器里存放对象

    #include 
    #include 
    #include 
    using namespace std;
    class Animal
    {
    public:
    	Animal(string name)
    	{
    		this->name = name;
    		cout<<"struct"<<endl;
    	}
    	Animal()
    	{
    		cout<<"default-struct"<<endl;
    	}
    	~Animal()
    	{
    
    	}
    	Animal(const Animal & T)
    	{
    		this->name = T.name;
    		cout<<"copy:"<<T.name<<endl;
    	}
    	void speak()
    	{
    	
    		cout<<"my name is "<<name<<endl;
    	}
    	void set(string name)
    	{
    		this->name = name;
    	}
    
    private:
    	string name;
    };
    
    int main()
    {
    	Animal T1("xx1");
    	Animal T2("xx2");
    	Animal T3("xx3");
    	Animal T4("xx4");
    	Animal T5("xx5");
    	Animal T6("xx6");
    	vector<Animal> t_vObject;
    	//t_vObject.clear();
    	t_vObject.push_back(T1);
    	t_vObject.push_back(T2);
    	t_vObject.push_back(T3);
    	t_vObject.push_back(T4);
    	t_vObject.push_back(T5);
    	t_vObject.push_back(T6);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行截图

    结论1.1

    由结果可见在构造animal对象时,会调用构造函数,在往vector里面装对象时,调用了拷贝构造函数,说明vector里面存放对象时,是将原来的对象进行了复制,由打印的情况来看,进行了多次复制,进行探究后发现是因为vector扩容时会将之前的部分进行复制,所以每一次扩容就会进行一个整体复制。我们改进代码:进行初始大小设定

    改进1.2

    int main()
    {
    
    	Animal T1("xx1");
    	Animal T2("xx2");
    	Animal T3("xx3");
    	Animal T4("xx4");
    	Animal T5("xx5");
    	Animal T6("xx6");
    	vector<Animal> t_vObject(10);
    	t_vObject.clear();
    	t_vObject.push_back(T1);
    	t_vObject.push_back(T2);
    	t_vObject.push_back(T3);
    	t_vObject.push_back(T4);
    	t_vObject.push_back(T5);
    	t_vObject.push_back(T6);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    我们给容器一个初始大小,然后将容器清空,此时容器就有了十个大小的容量,再往里面装对象时,就不会出现多次扩容的情况。
    运行截图

    2 vector容器里存放对象指针

    int main()
    {
    
    	Animal *dog=new Animal("dog");
    	Animal *cat=new Animal("cat");
    	Animal *panda=new Animal("panda");
    
    	vector<Animal*> t_vAnimals(10);
    	t_vAnimals.push_back(cat);
    	t_vAnimals.push_back(dog);
    	t_vAnimals.push_back(panda);
    
    	vector<Animal*> t_vAnimalscopy = t_vAnimals;
    	
    	for (int i=0; i< t_vAnimalscopy.size(); i++)
    	{
    		t_vAnimalscopy[i] = nullptr;
    	}
    	t_vAnimalscopy.clear();
    	int num = t_vAnimalscopy.size();
    	cout<<"t_vAnimalscopy.size() ="<<num<<endl;
    	int num2 = t_vAnimals.size();
    	cout<<"t_vAnimals.size() ="<<num2<<endl;
    
    
    	for (int i=0;i< t_vAnimals.size(); i++)
    	{
    		if (t_vAnimals[i] == nullptr)
    		{
    			cout<<"pointer is null"<<endl;
    			continue;
    		}
    		t_vAnimals[i]->speak();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    结果2.1

    由打印结果可见,在构造对象指针时,只会在new的时候调用构造函数。在对容器里面装指针时,应该也是进行了指针变量的复制,但是指针变量指向的地址是相同的,然后我们对容器进行复制后发现,在进行容器复制时,也是进行了变量的复制。由结果可见复制的大小已经为空了,但是原来的还能正常speak,说明地址的内容还在。
    运行截图

    探究2.2

    我们将复制的那一份数据擦除掉,即在遍历时,将里面的每一个数据都进行delete。最后得到初始的容器里的那一份数据会出现指针错误的提示,这说明,他们的地址是一样的,调用delete释放了那一块内存,此时会自动调用析构函数,也就是对象也就没了。

    	Animal *dog=new Animal("dog");
    	Animal *cat=new Animal("cat");
    	Animal *panda=new Animal("panda");
    
    	vector<Animal*> t_vAnimals(10);
    	t_vAnimals.push_back(cat);
    	t_vAnimals.push_back(dog);
    	t_vAnimals.push_back(panda);
    
    	vector<Animal*> t_vAnimalscopy = t_vAnimals;
    	
    	for (int i=0; i< t_vAnimalscopy.size(); i++)
    	{
    		delete t_vAnimalscopy[i];
    		t_vAnimalscopy[i] = nullptr;
    	}
    	t_vAnimalscopy.clear();
    	int num = t_vAnimalscopy.size();
    	cout<<"t_vAnimalscopy.size() ="<<num<<endl;
    	int num2 = t_vAnimals.size();
    	cout<<"t_vAnimals.size() ="<<num2<<endl;
    
    
    	for (int i=0;i< t_vAnimals.size(); i++)
    	{
    		if (t_vAnimals[i] == nullptr)
    		{
    			cout<<"pointer is null"<<endl;
    			continue;
    		}
    		t_vAnimals[i]->speak();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    运行截图

    运行截图

    验证2.3

    我们通过变量复制的那一份数据,对对象的名字进行更改,然后变量原始的数据容器,打印他们只向的对象的名字,发现名字已经被修改,说明他们指向的是同一个地址。

    int main()
    {
    
    	Animal *dog=new Animal("dog");
    	Animal *cat=new Animal("cat");
    	Animal *panda=new Animal("panda");
    	vector<Animal*> t_vAnimals;
    	t_vAnimals.push_back(cat);
    	t_vAnimals.push_back(dog);
    	t_vAnimals.push_back(panda);
    	vector<Animal*> t_vAnimalscopy = t_vAnimals;
    	for (int i=0; i< t_vAnimalscopy.size(); i++)
    	{
    		t_vAnimalscopy[i]->set("coco");
    	}
    
    	for (int i=0;i< t_vAnimals.size(); i++)
    	{
    		if (t_vAnimals[i] == nullptr)
    		{
    			cout<<"pointer is null"<<endl;
    			continue;
    		}
    		t_vAnimals[i]->speak();
    	}
    
    	getchar();
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    运行截图

    3总结

    在往容器里面装数据时,数据会进行复制。若数据为对象,则会调用对象的复制构造函数。若对象时指针则不会调用复制构造函数,此时复制的的指针变量,只不过变量指向的地址是一样的。对容器进行清空,调用delete会释放对象,同时调用析构函数。对复制的指针数据进行修改,原始的数据也会修改,说明复制对象指针时,其实只有一份数据。

  • 相关阅读:
    Flutter: FutureBuilder 组件的使用
    Spring Boot日志文件
    c语言变长数组的实现
    dede:arclist标签判断有缩略图则显示否则不显示或显示其他自定义图片
    网页制作课作业基于HTML+CSS+JavaScript+jquery仿慕课网教学培训网站设计实例 企业网站制作
    tsx 文件中的 行删除
    力扣HOT100 - 108. 将有序数组转换为二叉搜索树
    Hive分区表和分桶表
    Nanoprobes丨Nanogold 标记条带的凝胶染色
    金仓数据库KingbaseES安全指南--9.透明存储加密
  • 原文地址:https://blog.csdn.net/qq_43611366/article/details/127724986