C++容器的遍历与程序的性能分析

c++11之后,c++可能是受到java等语言的启发,引入了更多的遍历容器的方式,但是,如果使用方式不对,可能会导致程序的性能低下。本例就使用了多种遍历方式来访问list的元素。并演示了其中的区别。

这段代码演示了如下C++的特点:
1、对list等容器的元素来遍历的时候,如果元素是非指针类型,使用迭代器的速度要比使用 for( auto ele:list_name) 的方式快。for( auto ele:list_name)的方式,ele是个临时变量,这种方式不能修改list_name中的元素本身。但是使用for( auto & ele:list_name)可以修改list_name中的元素本身,for( auto ele:list_name)的性能与迭代器的性能相当;
2、例子中计算性能的方式不太严谨,可以去掉每个循环中的循环体和增加循环次数来更加精确的演示速度的快慢。
3、如果list等容器的元素类型是非指针类型,使用一个变量名字去添加元素的时候,会在堆中产生临时变量,这些临时变量会放在容器中。
4、如果list等容器的元素类型是指针类型,使用迭代器和for( auto ele:list_name)  和 for( auto & ele:list_name) 的性能相当,因为遍历这些元素不会产生临时变量。
5、在析构对象的时候,堆中的对象,是先创建的先析构,栈中的对象析构顺序符合栈的特点:后创建的先析构,即“弹栈式”的析构。
6、本例使用了list容器,而没有使用vector,使用vector的话,如果元素是非指针类型,则vector本身创建的时候,就会有很多次的构造和析构,这是因为vector的元素的地址是连续的。一旦内存中的某个地址装不下当前的元素的时候,系统会去寻找更大的地址来装更多的元素,这个地址的改变就要涉及到对象的复制构造和析构。而list则没有这个缺点,它是“链表式”的保存元素。
7、如果追求性能,需要使用list,且元素类型须是指针类型。

// g++ -std=c++11 list_for.cpp -o list_for

#include <iostream>
#include <string>
#include <list>
#include <chrono>

#define STD_COUT std::cout<<__FILE__<<":"<<__LINE__<<"@"<<__FUNCTION__<<"\t"

class ClassA
{
public:
    ClassA()
    {
        STD_COUT <<this<<" default constructor"<<std::endl;
        m_iNum = 0;
    }

    ClassA(const ClassA & a)
    {
        STD_COUT <<this<<" copy constructor 1"<< std::endl;
        this->m_iNum = a.m_iNum;
        this->str_msg_ = a.str_msg_;
    }

    ClassA operator = (const ClassA & a){
        STD_COUT <<this<<" copy constructor 2"<<std::endl;
        this->m_iNum = a.m_iNum;
        this->str_msg_ = a.str_msg_;
        return *this;
    }

    virtual ~ClassA()
    {
        STD_COUT <<this<< std::endl;
        m_iNum = 0;
    }

    virtual void showMsg()
    {
        STD_COUT << "from ClassA " <<this<< std::endl;
    }

    virtual void callMsg()
    {
        this->showMsg();
    }

public:
    int m_iNum;
    std::string str_msg_;
};

int main(int argc, char ** argv){
	std::cout <<"=============在栈中创建一个对象================= "<<(void*)&main << std::endl;
    ClassA class_a1;
    
    std::list<ClassA> myList2;
    for(int i =0; i< 5;i++){
        if(class_a1.str_msg_.length() < 2000){
            class_a1.str_msg_.append("this is s string");
        }
        class_a1.m_iNum = i;
        std::cout <<"=============加入一个元素,这里会产生复制构造出临时变量放到list中================="<< std::endl;
        myList2.push_back(class_a1);
    }

    // 当前微秒
    long long micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;

    for(std::list<ClassA>::iterator itr = myList2.begin(); itr != myList2.end() ; itr++){
    	std::cout <<"元素中的地址 "<<(void*)&(*itr)<< std::endl;
    }

    long long micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用迭代器的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;


    for(auto ele: myList2){
    	std::cout <<"元素中的地址 "<<(void*)&(ele)<< std::endl;
    }

    micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用 auto 的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;


    for(auto & ele: myList2){
    	std::cout <<"元素中的地址 "<<(void*)&(ele)<< std::endl;
    }

    micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用 auto & 的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    std::cout <<"=============在堆中创建一个对象=================" << std::endl;
	std::list<ClassA*> myList;
    for(int i =0; i< 5;i++){
    	ClassA* class_a2 = new ClassA();
        if(class_a2->str_msg_.length() < 2000){
            class_a2->str_msg_.append("this is s string");
        }
        class_a2->m_iNum = i;

        myList.push_back(class_a2);
    }

    // 当前微秒
    micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;

    for(std::list<ClassA*>::iterator itr = myList.begin(); itr != myList.end() ; itr++){
    	std::cout <<"元素中的地址 "<<(void*)&(*itr)<< std::endl;
    }

    micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用迭代器的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;


    for(auto ele: myList){
    	std::cout <<"元素中的地址 "<<(void*)&(ele)<< std::endl;
    }

    micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用 auto 的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    micro_seconds1 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds1 << std::endl;


    for(auto & ele: myList){
    	std::cout <<"元素中的地址 "<<(void*)&(ele)<< std::endl;
    }

    micro_seconds2 = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    std::cout <<"当前微秒\t"<< micro_seconds2 << " 使用 auto & 的时间差 "<<micro_seconds2-micro_seconds1 << std::endl;

    std::cout <<"=============手动析构堆中的变量=================" << std::endl;
    for(auto & ele: myList){
    	delete ele;
    }
    std::cout <<"=============程序结束,自动析构栈中的变量=================" << std::endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值