c++之vector以及deque的一些思考,以及pop与push的具体实现

今天在分析threadsafe_stack代码时发现自己对pop和push的具体实现原理以及注意事项还是有点疏漏,然后撸了一遍相关标准库代码,记录一下。
先说结论:

  1. pop与erase只是移动指针,不会删除内存,但是会调用该位置的析构函数,所以直接用变量引用这块内存是可以的,且不会出错
  2. emplace与push如果都是传入右值,那么实际使用上的区别就是emplace的不会调用析构函数,push进去的会调用析构函数
  3. move拷贝完了,原来的对象是会析构的

pop与erase

下图为vector< T>的pop_back的调用关系,其内部只是将M_impl._M_finish指针- -,然后调用该T的析构函数。并未完成该对象在该内存的清理,所以后续可以通过指针与引用对该地址进行操作。erase同理,内部函数调用比较类似。
在这里插入图片描述

emplace与push

emplace与push两者如果传入的是右值,则都是调用emplace_back
区别在于两者在placement_new那个点调用的构造函数不同,前者是调用构造函数,后者调用拷贝构造函数,所以push之后是需要调用析构,而emplace不需要
在这里插入图片描述

示例代码

#include <exception>
#include <memory>
#include <mutex>
#include <stack>
#include <iostream>
#include <vector>
class Test
{
    public:
    Test(int a):b(a){std::cout<<"Test "<<b<<std::endl;};
    Test(Test&& t){this->b = t.b; t.b = 0; std::cout<<"Test&& "<<b<<std::endl;}
    ~Test(){std::cout<<"~Test "<<b<<std::endl;};
    int b;
};
int main()
{
    std::vector<int> v{1,2,3};
    v.pop_back();  
    // v.erase(v.end()-1);
    std::cout<<"vector "<<v.back()<<"and "<<*(v.data()+2)<<std::endl;

    // threadsafe_stack<int> ts;
    std::stack<Test> a;
    a.push(1);  //  Test 1,Test&& 1, ~Test 0
    a.emplace(2);  // Test 2,这里没有后面两个,根据上面的分析可得知啦
    
    Test& value = a.top();  //这里value引用了top(),虽然被pop了,但是其值还在
    a.pop();   // ~Test 2
    std::cout<<"value of pop is "<< value.b<<" and "<<a.top().b<<std::endl;  //value of pop is 2 and 1
}
vector 2and 3
Test 1
Test&& 1
~Test 0
Test 2
~Test 2
value of pop is 2 and 1
~Test 1
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值