面试十六、emplace原理


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


class Test{
public:
    Test(int a) {cout <<"Test(int)" << endl; }
    Test(int a,int b) {cout <<"Test(int,int)" << endl; }
    ~Test(){cout << "~Test()"<< endl;}
    Test(const Test&) {cout <<"Test(const Test&)" << endl; }
    Test(Test&&) {cout <<"Test(Test&&)" << endl; }
};

template<typename T>
struct MyAllocator{
    T* allocate(size_t size){
        return (T*) malloc(size * sizeof(T));
    }

    template<typename... Types>
    void construct(T* ptr , Types&&... args){
        new (ptr) T(std::forward<Types>(args)...);
    }
};



template< typename T,typename Alloc =MyAllocator<T>>
class Vector{


    // 实参:  左值  =》 Types 为  Test&  右值引用变量不可能去引用一个左值,应该是 Test& +&& => Test&,怎args的类型为左值引用
    //        右值 =》  Types 为  Test&&  右值引用变量右值    Test&& + && => Test&&

    // emplace_back 接受多个类型参数,比如可能是引用,右值引用,int类型,多个int类型等,向容器插入对象
    // 其底层是使用可变参数模板,完美转发,引用折叠实现的 , 首先emplace_back方法接收多个参数,然后调用容器的空间配置器,向已存在的空间上
    // 使用定位new构建对象,而空间配置器的construct方法,也需要接受多个参数,在此过程中需要使用完美转发,保证左值引用还是左值引用,右值引用还是右值引用
    // 然后将使用 定位new 构造对象new (ptr) T(std::forward<Types>(args)...); 根据接受参数的类型和个数选择构造对象的方法。
    template<typename... Types>
    void emplace_back(Types&&... args){
        // 不管是左值引用变量还是右值引用变量,变量本身是个左值 ,传递过程中,要保证args的引用类型,使用完美转发
        allocator_.construct(vec_+idx_ , std::forward<Types>(args)...);
        idx_++;
    }

    template<typename Type>
    void push_back(Type&& val){
        allocator_.construct(vec_+idx_ , std::forward<Type>(val));
        idx_++;
    }





private:
    T* vec_;
    int size_;
    int idx_;
    Alloc allocator_;
};

















#if 0
class Test{
public:
        Test(int a) {cout <<"Test(int)" << endl; }
        Test(int a,int b) {cout <<"Test(int,int)" << endl; }
        ~Test(){cout << "~Test()"<< endl;}
        Test(const Test&) {cout <<"Test(const Test&)" << endl; }
        Test(Test&&) {cout <<"Test(Test&&)" << endl; }
};


int main(){
    Test t1(10);
    vector<Test>v;
    v.reserve(100);

    cout << "============================"<< endl;
    // 直接插入对象是没有区别的
    v.push_back(t1);
    v.emplace_back(t1);
    cout << "============================"<< endl;

    // 直接插入对象是没有区别的
    //
    //右值引用的拷贝构造函数通常比普通的拷贝构造函数更高效,因为右值引用允许在移动语义下进行操作,
    // 而不是简单地复制数据。右值引用的拷贝构造函数通常会将资源的所有权从一个临时对象(右值)转移到目标对象上,而不是简单地复制数据。
    //而对于右值引用的拷贝构造函数,可以直接将源对象的指针指向新的目标对象,而不需要进行额外的内存分配和释放。
    //当临时对象的资源被移动到目标对象之后,临时对象仍然会被销毁。尽管资源的所有权已经转移,但是临时对象本身还是会经历析构过程。
    v.push_back(Test(20));
    v.emplace_back(Test(20));

    cout << "============================"<< endl;
    // 给emplace传入Test构造函数所需要的参数,会再容器底层构造对象
    v.emplace_back(20);
    v.emplace_back(20,30);
    cout << "============================"<< endl;
    return 0;
}
#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值