IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】使用容器管理对象注意事项 -> 正文阅读

[C++知识库]【C++】使用容器管理对象注意事项

标题取的不太恰当,实际是:对象浅拷贝的陷阱。

将局部对象变量放入容器中进行管理需要特别小心(存在重复析构成员变量为指针类型的属性),直接上代码看:

#include <vector>
#include <string>
#include <iostream>
using namespace std;

class Person {
public:
	Person(string name) : pName_(new string(name)) {}
	// Person(const Person& person);
	~Person() { 
		cout << *pName_ << " deleted" << endl;
		delete pName_; 
	}
	void printName() { cout << *pName_ << endl; }

private:
	string* pName_;
};

int main() {
	vector<Person> persons;
	Person p("George");
	persons.push_back(p);

	persons.front().printName();

	cout << "Goodbye " << endl;
	
	return 0;
}

在main函数return前:
1.向量对象persons会被析构,并且其中的元素也会调用对应的析构函数进行析构(调用~Person);
2.局部对象p也会被析构;

初看好像没有什么问题,但是局部对象b会被编译器默认的拷贝构造函数(Copy constructer)浅拷贝一份放入persons向量中。如此b对象的string *pName_指针同时被2个对象拥有,那么就存在~Person()重复delete pName_的现象

?在C++11版本中如何处理这个问题?

使用移动构造函数 + 智能指针: 效率高,不用重复创建pName_ 。

#include <vector>
#include <string>
#include <iostream>
using namespace std;

class Person {
public:
	Person(string name) : pName_(new string(name)) {}
	Person(const Person& person) = delete;
	~Person() { }

	Person(Person&&) = default;
	void printName() { cout << *pName_ << endl; }

private:
	std::unique_ptr<string> pName_;  // 使用shared_ptr有点浪费
};

int main() {
	vector<Person> persons;
	Person p("George");
	persons.push_back(std::move(p));
	// p 对象被Move Construct,已经不能使用
	persons.front().printName();

	cout << "Goodbye " << endl;
	
	return 0;
}

在C++03版本中如何处理这个问题?

不采用编译器提供的默认“拷贝构造函数、赋值构造函数”,类中存在指针属性,直接使用默认的这2个构造函数是非常危险的。直接显示编写这2个构造函数!

效率没有C++11版高(这就体现了移动构造的高效率),其他无差异。

#include <vector>
#include <string>
#include <iostream>
using namespace std;

class Person {
public:
	Person(string name) : pName_(new string(name)) {}
	Person(const Person& person){
		this->pName_ = new string(*person.pName_);
	}
	~Person() {
		cout << *pName_ << " deleted" << endl;
		delete pName_;
	}

	Person(Person&&) = default;
	void printName() { cout << *pName_ << endl; }

private:
	string* pName_;
};

int main() {
	vector<Person> persons;
	Person p("George");
	persons.push_back(p);  // 使用自定义的拷贝构造函数深度复制p对象

	persons.front().printName();

	cout << "Goodbye " << endl;
	
	return 0;
}


?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 01:23:14  更:2021-08-17 01:23:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 4:26:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码