拷贝构造函数的第一个参数要求是自身类型的引用,但是没有一定要求具有底层const属性即对常量的引用,但是使用时最好加上const,原因是我们可能在某些“不知道”的情况下对常量对象调用拷贝构造函数。

  来看一个例子

class HasPtr{
public:
HasPtr(const std::string &s=std::string()):ps(new std::string(s)),i(0){
std::cout<<"construction call"<<std::endl;
}
HasPtr(HasPtr &hasptr):i(hasptr.i),ps(new std::string(*hasptr.ps))
{
std::cout<<"copy construction call"<<std::endl;;
}
~HasPtr()
{ delete ps;
std::cout<<"deconstruction call"<<std::endl; }
private:
std::string *ps;
int i;
};
int main()
{
HasPtr ptr1("a"),ptr2("c"),ptr3("b");
std::vector<HasPtr> vec{ptr1,ptr2,ptr3};
return 0;
}

  上面的例子中定义了一个类HasPtr,此类包含一个参数为自身类型引用的拷贝构造函数,主程序中构造了三个类的实例化对象,使用初始化列表的方式将其放入容器vector中。看上去好像没有什么问题,但是这个例子会在编译期出错。

 error: cannot bind non-const lvalue reference of type ‘HasPtr&’ to an rvalue of type ‘HasPtr’

  程序中所有地方均使用HasPtr的对象均为左值为什么会报无法从非常量的左值无法绑定到右值上去?

  答案是,在初始化初始化列表的时候,vector的构造函数匹配vector<T>(initializer_list<T>)这个构造函数,而initializer_list<T>的元素均为const。这里程序作了三个操作:

  1、首先将初始化列表中的值拷贝构造到initializer_list中,此处HasPtr具有了const属性,成为了一个右值。(产生三个对象)

  2、然后程序将initializer_list中的元素拷贝构造到vector中 (产生三个对象)

  3、销毁initializer_list中的元素 (销毁三个对象)

  上述第二步操作需要调用参数为const HasPtr &的拷贝构造函数,而我们提供的是非const版本的,所以需要隐式转换,但显然这样的转换是失败的,所以产生上述错误。

  

  总结:1、拷贝构造函数的第一个参数最好带上const

     2、包含初始化列表的容器操作可能会调用两次拷贝构造函数。

拷贝构造函数第一个参数最好使用const的更多相关文章

  1. C++ 拷贝构造函数、拷贝赋值运算符、析构函数

    每一次都会忘,做个笔记吧.想到哪里写到哪里. 拷贝构造函数 第一个参数必须是自身类类型的引用,且任何额外参数都有默认值.(为什么必须是引用?见后解释) 合成拷贝构造函数:如果我们没有为一个类定义拷贝构 ...

  2. [C++参考]拷贝构造函数的参数必须是引用类型

    在C++中, 构造函数,拷贝构造函数,析构函数和赋值函数(赋值运算符重载)是最基本不过的需要掌握的知识.在effective C++中说过这么一点:拷贝构造函数的参数必须是引用类型的.但是为什么呢? ...

  3. 初始化列表(const和引用成员)、拷贝构造函数

    一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一).对象成员及其初始化  C++ Code  1 2 3 4 5 6 7 8 9 1 ...

  4. 【转】C++的拷贝构造函数深度解读,值得一看

    建议看原帖  地址:http://blog.csdn.net/lwbeyond/article/details/6202256 一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很 ...

  5. [Reprint]C++友元函数与拷贝构造函数详解

    这篇文章主要介绍了C++友元函数与拷贝构造函数,需要的朋友可以参考下   一.友元函数 1.友元函数概述: (1)友元函数是定义在一个类外的普通函数.友元函数和普通函数的定义一样;在类内必须将该普通函 ...

  6. C++拷贝构造函数详解(转载)

    一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员 ...

  7. 【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解

     c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3 ...

  8. [016]转--C++拷贝构造函数详解

    一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员 ...

  9. C++拷贝构造函数详解 转

    一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: [c-sharp] view plaincopy int a = 100; int b = a; 而类对象与普通 ...

随机推荐

  1. 运维干货|交换机不同VLAN之间及相同VLAN之内进行隔离

    文中所展示的内容为VLAN与VLAN之间分隔关系,如相同VLAN用户之间进行分隔,相同VLAN一组用户之间允许通信并与其它一组用户之间进行分隔,属于VLAN的高级应用范畴.本文来源于智象运维某大神的日 ...

  2. go中semaphore(信号量)源码解读

    运行时信号量机制 semaphore 前言 作用是什么 几个主要的方法 如何实现 sudog 缓存 acquireSudog releaseSudog semaphore poll_runtime_S ...

  3. windows平台 cloin +rust 开发环境搭建

    rust 安装请看上一篇 clion 下载地址 破解 教程 1.先执行reset_jetbrains_eval_windows.vbs 2.打开软件选择免费使用 将ide-eval-resetter- ...

  4. [源码解析] 并行分布式任务队列 Celery 之 消费动态流程

    [源码解析] 并行分布式任务队列 Celery 之 消费动态流程 目录 [源码解析] 并行分布式任务队列 Celery 之 消费动态流程 0x00 摘要 0x01 来由 0x02 逻辑 in komb ...

  5. 华为云PB级数据库GaussDB(for Redis)揭秘第七期:高斯Redis与强一致

    摘要:在KV数据库领域,"强一致性"不仅是一个技术名词,它更是业务与运维的重要需求. 清明刚过,五一假期就要来了.大好春光,不如去婺源看油菜花吧!小云迅速打开APP刷出余票2张,赶 ...

  6. 恒骊学堂的JAVA初步学习总纲--转载

  7. Spring Boot 整合Junit和redis

    14. Spring Boot整合-Junit 目标:在Spring Boot项目中使用Junit进行单元测试UserService的方法 分析: 添加启动器依赖spring-boot-starter ...

  8. inline&register

    inline关键字: 内联只是一个请求,不代表编译器会响应:同时某些编译器会将一些函数优化成为内联函数. C++在类内定义的函数默认是内联函数,具体是否真变成内联函数还需看编译器本身. registe ...

  9. 在Android、iOS、Web多平台使用AppGallery Connect性能管理服务

    性能管理(App Performance Management,简称APM)是华为应用市场AppGallery Connect(简称AGC)质量系列服务中的其中一项,可以提供分钟级应用性能监控能力,支 ...

  10. 统计学习方法——实现AdaBoost

    Adaboost 适用问题:二分类问题 模型:加法模型 \[f(x)=\sum_{m=1}^{M} \alpha_{m} G_{m}(x) \] 策略:损失函数为指数函数 \[L(y,f(x))=ex ...