C++更快的Vector容器

1、简单介绍std::vector<class T>

        相信很多写过C++程序的朋友对std::vector<class T>这个容器并不会感到陌生,可能有很多的新人朋友刚开始对于std::vector<class T>容器的使用方式和下面的案例是差不多的。

   int main() {
	
	Book book1("格林童话", 1);
	Book book2("安徒生童话", 2);
	Book book3("老人与海", 3);
	Book book4("肖申克的救赎", 4);

	std::vector<Book> library;
	library.push_back(book1);
	library.push_back(book2);
	library.push_back(book3);
	library.push_back(book4);

	return 0;
}

        当我们想要把某个数据类型的数据制作成一个集合的时候这样做也是无可厚非的,而且这种方式使用起来也是非常的简单。

2、存在的一些问题

        上面的方法在使用std::vector<class T>容器在存储数据时使用起来非常的省事,但是这也做其实整个程序的效率是非常的糟糕的,下面举个例子

先定义一个Book 类型的结构体

#ifndef BOOK
#define BOOK
struct Book{
	std::string mName;
	int mID;

	Book(const std::string& iName, int iID);
	Book(const Book& iBook);
	~Book() {}
};

Book::Book(const std::string& iName, int iID):
	mName(iName),
	mID(iID) {
	std::cout << "Construct function has be called" << std::endl;
}

Book::Book(const Book& iBook) {
	mName = iBook.mName;
	mID = iBook.mID;
	std::cout << "Copy function has be called" << std::endl;
}
#endif // !BOOK

再使用下面的代码进行测试

int main() {
	
	Book book1("格林童话", 1);
	Book book2("安徒生童话", 2);
	Book book3("老人与海", 3);
	Book book4("肖申克的救赎", 4);

	std::cout << "\n";

	std::vector<Book> library;
	library.push_back(book1);
	library.push_back(book2);
	library.push_back(book3);
	library.push_back(book4);

	return 0;
}

程序运行的结果如下

构造函数调用的4次,可是复制函数却调用了10次,简直难以想象。

3、导致问题的原因

        我们在使用std::vector<class T>容器时并没有去声明需要多大的空间,这就导致了下面的事情发生:每当我们调用std::vector<class T>::push_back(T)函数的时候,std::vector<class T>需要去找一个新的地址然后开辟出足够的空间,将原来存放在容器中的数据和push_back()当中的数据全部拷贝到新的地址当中。根据上面的测试代码我们就可以得出,拷贝代码一共执行了 4 + 3 + 2 + 1 = 10;如果我们需要放入n个数据,那么拷贝代码要执行的次数就是 \frac{n*(n+1)}{2},计算的复杂程度是n^{2}

4、解决问题的方法

        想要解决这个问题其实也非常的简单,只需要声明一下容器需要的空间大小就可以了。

int main() {
	
	Book book1("格林童话", 1);
	Book book2("安徒生童话", 2);
	Book book3("老人与海", 3);
	Book book4("肖申克的救赎", 4);

	std::cout << "\n";

	std::vector<Book> library;
	library.reserve(4);        //声明需要放入四个该数据类型

	library.push_back(book1);
	library.push_back(book2);
	library.push_back(book3);
	library.push_back(book4);

	return 0;
}

运行的结构如下

我们可以看到拷贝函数只执行了4次,计算的复杂程度一下子就变成了n。这一下效率就高多了。

5、更加的高效

        虽然已经大幅度降低了计算的复杂程度,但是我还可以进一步的提高效率,那就是我们在制作这个数据集合的时候,去除掉拷贝这个步骤。那么我们就要使用C++11当中的新函数std::vector<class T>::emplace_back(...),请看下面的案例

int main() {
	
	std::vector<Book> library;
	library.reserve(4);

	library.emplace_back("格林童话", 1);
	library.emplace_back("安徒生童话", 2);
	library.emplace_back("老人与海", 3);
	library.emplace_back("肖申克的救赎", 4);
	

	return 0;
}

运行结果如下

这下我们的程序就更快了。

6、注意事项

        如果存放的数据超过了声明的个数,那么std::vector<class T>容器依然会寻找新的地址开辟足够的空间,将先前的数据拷贝到新的地址当中案例如下

int main() {
	
	std::vector<Book> library;
	library.reserve(4);

	library.emplace_back("格林童话", 1);
	library.emplace_back("安徒生童话", 2);
	library.emplace_back("老人与海", 3);
	library.emplace_back("肖申克的救赎", 4);
	library.emplace_back("猫和老鼠", 5);
	

	return 0;
}

运行结构如下

7、总结

        在使用std::vector<class T>容器时,能够确定存放数据的个数时,那么就事先声明容器的大小,为减少拷贝的次数尽可能使用新函数std::vector<class T>::emplace_back(...),这样我们的程序的运行效率就会有大幅度的提升

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值