c++ stl queue的使用

14 篇文章 0 订阅

        队列不是真正的窗口,而是一种容器适配器,专门设计用于在FIFO上下文中操作(先进先出),其中元素被插入到容器的一端,并从另一端提取。它包含了另外一种容器,且进行了包装,看其定义如下:

第二个参数指定了queue的底层实现类型,这里默认为 std::deque,也可以是其他任意类型,只要支持front, back, push_back, pop_front等操作。

        今天主要看其的两个接口,因为之前一直有疑惑,即 front() 和 pop()。一个是获取队首元素, 一个是弹出队首元素。代码如下:

#include <queue>
#include <iostream>
#include <string.h>

class CData
{
public:
    CData(int value): mValue(value)
    {

    }

    CData(const CData& another)
    {
        mValue = another.mValue;
        std::cout << "copy construtor" << std::endl;
    }
    ~CData()
    {
        std::cout << "destructor" << std::endl;
    }

    void print()
    {
        std::cout << mValue << std::endl;
    }

private:
    int mValue;
};

int main()
{ 
    std::queue<CData> dataQueue;
    
    CData test1(10);
    dataQueue.push(test1);

    std::cout << "before front" << std::endl;
    CData data = dataQueue.front();
    dataQueue.pop();
    std::cout << "finish front" << std::endl;
    
    data.print();

    return 0;
}

我们知道,调用 front() 返回的是一个引用,而代码实际运行结果为:

1,在调用 front() 时调用在类的拷贝构造函数,在调用 pop() 时调用了类的析构函数。疑惑的是front() 不是返回元素的引用吗?怎么会调用拷贝构造函数呢?原因为:front() 返回值赋值给的普通变量,变量 data 取到的应该是该元素的一份拷贝,如果用引用变量去接收,则不会调用拷贝构造函数,如改成:CData &data = dataQueue.front(); 其结果就不会调用拷贝构造函数,如:

 2,在调用 pop() 时会调用元素的析构函数,队列大小减 1。但需要注意的是元素占用的内存并未释放,直到队列被析构。

 我们从GDB 里看一看:

在运行到 CData &data = dataQueue.front(); 其内存地址是 0x400a50,成员数据随机的,再调用front()后,data指向了队列元素,其地址为:0x605060,打印出成员数据是 10,当执行完pop()后,data还是指向原地址,而CData的析构函数只是输出一行打印信息并没做其他操作。如果你类类型里有资源的申请(如new 或 malloc),而在析构里已经释放资源,在调用 pop() 后,千万在小心使用,如:

#include <queue>
#include <iostream>
#include <string.h>

class CData
{
public:
    CData(int value): mValue(value)
    {
        mPtr = new char[20];
    }

    CData(const CData& another)
    {
        mValue = another.mValue;
        std::cout << "copy construtor" << std::endl;
    }
    ~CData()
    {
        std::cout << "destructor" << std::endl;
        delete []mPtr;
    }

    void print()
    {
        std::cout << mValue << std::endl;
        const char *str = "test";
        memcpy(mPtr, str, strlen(str));
    }

private:
    int mValue;
    char *mPtr;
};

int main()
{ 
    std::queue<CData> dataQueue;
    
    CData test1(10);
    dataQueue.push(test1);

    std::cout << "before front" << std::endl;
    CData &data = dataQueue.front();
    dataQueue.pop();
    std::cout << "finish front" << std::endl;
    
    data.print();

    return 0;
}

在调用 pop() 后,还去调用 print() 接口,而此接口里却用到的指针,程序则会出现segmentation fault :

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值