C++,vector<T>::insert()和push()调用拷贝构造而emplace()根据传入参数列表做函数匹配决定调用自定义构造函数或拷贝构造函数

本文通过具体示例解析了C++中Type类的各种构造方式,包括默认构造、自定义构造、拷贝构造及析构的过程。展示了在使用std::vector时不同插入方式对构造与拷贝的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《C++ Primer》拷贝、赋值与销毁,P441:

 

 

class Type{
    public:
    string str;
    Type():str(""){                     // 默认构造
        cout<<"calling Type()"<<endl;
    }
    Type(string strv):str(strv){        // 自定义构造
        cout<<"calling Type(string)"<<endl;
    };
    Type(const Type &obj):str(obj.str){ // 拷贝构造
        cout<<"calling Type(const Type &)"<<endl;
    };
    ~Type(){
        cout<<"calling ~Type()"<<endl;
    }
};
int main(int argc,char **argv){
    vector<Type> arr(2);    
    /* 共调用1次默认构造、2次拷贝构造、3次析构,
    默认构造1个实例后拷贝构造两个实例到vector,最后3个实例全部析构
    1、拷贝构造的确是构造,是从无到有,错误认知是”默认构造两个实例后拷贝到这两个实例“
    */
    cout<<"&arr[0]: "<<&arr[0]<<endl;   // 输出扩容前的数组起始地址
    cout<<"0"<<endl;
    Type *pobj = new Type((string)"a");
    Type &obj(*pobj);
    cout<<"1"<<endl;
    arr.insert(arr.end(),obj);   // 等价于arr.push(obj)
    // arr.push_back(obj);       // 等价于arr.insert(arr.end(),obj)
    /* 扩容调用两次拷贝构造“移动”已有的两个元素,insert()时又调用一次拷贝构造
    insert()结束后析构旧地址的两个元素
    */
    cout<<"&arr[0]: "<<&arr[0]<<endl;   // 输出扩容后的数组起始地址
    cout<<"size: "<<arr.size()<<endl;   // 3
    arr.emplace(arr.end(),(string)"b"); 
    /*emplace()根据传入的参数列表进行函数匹配,调用了自定义构造函数
    ,不像insert()或push()调用拷贝构造*/
    cout<<"size: "<<arr.size()<<endl;   // 4
    arr.emplace(arr.end(),obj); // 将调用拷贝构造函数
    cout<<"2"<<endl;
    delete pobj;        // 析构堆上对象
    cout<<"3"<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值