拷贝构造函数的第一个参数要求是自身类型的引用,但是没有一定要求具有底层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. 云计算和AI时代,运维应该如何做好转型?

    云计算和AI时代,运维应该如何做好转型? 今天我们来聊一聊,在云计算和AI时代,运维应该如何做好转型?今天的内容可以说是我们前面运维组织架构和协作模式转型的姊妹篇.针对运维转型这个话题,谈谈我的思考和 ...

  2. 从 lite-apiserver 看 SuperEdge 边缘节点自治

    引言 在 SuperEdge 0.2.0版本中,lite-apiserver 进行了重大的架构升级和功能增强.本文将从 lite-apiserver 实现及其与其它 SuperEdge 组件协同的角度 ...

  3. shell字符串处理总结

    1. 字符串切片 1.1 基于偏移量取字符串 返回字符串 string 的长度 ${#string} 示例 [root@centos8 script]#str=" I Love Python ...

  4. Kafka核心技术与实战,分布式的高性能消息引擎服务

    Kafka是LinkedIn开发并开源的一套分布式的高性能消息引擎服务,是大数据时代数据管道技术的首选. 如今的Kafka集消息系统.存储系统和流式处理平台于一身,并作为连接着各种业务前台和数据后台的 ...

  5. 下载kaggle数据集的小妙招

    kaggle是很多数据分析和机器学习初学者非常喜爱的数据科学竞赛平台. 这个平台上有很多接近现实业务场景的数据集,非常适合练手. 今天向大家推荐一个下载kaggle数据集的小工具--kaggleAPI ...

  6. Palindromes UVA - 401

    ​ A regular palindrome is a string of numbers or letters that is the same forward as backward. For e ...

  7. Day13_71_线程同步(synchronized)

    线程同步 * 异步编程模型和同步编程模拟的区别? - 有T1和T2 两个线程 > 异步编程模型:T1线程执行T1的,T2线程执行T2的,谁也不等谁 > 同步编程模型:T1和T2 线程执行, ...

  8. 数据结构之栈(JavaScript描述)

    栈数据结构   栈是一种遵从后进先出原则的有序集合.新添加或待删除的元素都保存在栈的同一端,称为栈顶,另一端就叫栈底.在栈内,锌元素都靠近栈顶,救援都接近栈底 类似栈的例子   栈也被用在编程语言你的 ...

  9. 哈工大LTP进阶使用-三元组事件抽取

    哈工大LTP基本使用-分词.词性标注.依存句法分析.命名实体识别.角色标注 上一节我们讲了LTP的基本使用,接下来我们使用其进行事件抽取. 参考代码:https://github.com/liuhua ...

  10. 开坑:mysql相关问题

    一. 先过滤后连表和先连表后在mysql中选择的哪一种? 二. left join 和inner join使用场景有什么区别? 三. 第二个问题的衍生问题:left join中where 条件使用对n ...