过去在学习C++中类对象创建时,对constructor关注的很多,天真地认为了解了constructor,copy constructor,copy assignment就对类对象的创建理解了,今天遇到的一个看似不起眼的问题让我认识了还有copy initialization这么个东东,通过网上查阅揭开了copy initialization写神秘面纱,下面讲一下自己的一点理解。

首先看一下问题代码:

class String{
public:String() :str(""){ cout << "default constructor" << endl; }String(int n);String(const String &x) :str(x.str){cout << "copy constructor" << endl;}String& operator=(const String &x){str = x.str;cout << "operator =" << endl;return *this;}string getStr() const{return str;}
private:string str;
};ostream& operator<<(ostream &o,const String &x)
{o << x.getStr();return o;
}String::String(int n)
{stringstream ss;ss << n;ss >> str;ss.clear();ss.str("");cout << "String(int n)" << endl;
}int _tmain(int argc, _TCHAR* argv[])
{String s6 = 10;cout << s6 << endl;return 0;
}

运行结果如下图所示:

首先对于等式右边的10,能够理解使用了隐式转换调用了String(int n)创建了一个String对象,运行结果也确实是这样。但是为什么之后没有调用copy assignment等号操作符重载?原来关键是使用了copy initialization

其实,String s6 = 10;这不是一个赋值,这是一个初始化,准确的说是复制初始化(copy initialization)。

copy initializaiton: initializes an object from another object

copy initialization有以下几种形式:

T object = other; (1)  
 
T object = {other; (2) (until C++11)
 
f(other) (3)  
 
return other; (4)  
 
throw object;

catch (T object)

(5)  
 
T array[N] = {other}; (6)

本文中的是第一种形式。它的实现过程准确的说是:

If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary(until C++17)prvalue expression (since C++17) if a converting constructor was used, is then used to direct-initialize the object. The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

也就是说,当other不是T类或T类子类的对象时,将会选择一个最佳的转换函数将other转换成T类。在本文中String(int n)就是上文中的converting constructor,而converting constructor是属于user-defined conversion sequences的一部分。因此本文中String(int n)将会被调用将10转变为String对象,转换的结果是一个prvalue temporary(类似右值的临时值),这个prvalue temporary然后将被用来直接初始化(direct initialize)T类对象(在本文中就是s6)。但是直接初始化(direct initialize)这步通常被优化了,即转换的结果直接在内存中construct并且分配给目标对象。在本文中,就是在栈上调用String(10)创建了一个String类的对象,然后将这个对象直接给s6,过程等价于执行了s6(10),所以才会出现运行结果中的只执行了String(int n),并没有执行copy assignment,也就是上文所说的even though it's not used

自己的简单理解,如有错误,欢迎指正

参考链接:

copy initialization: http://en.cppreference.com/w/cpp/language/copy_initialization

converting constructor:http://en.cppreference.com/w/cpp/language/converting_constructor

[C++] - 中的复制初始化(copy initialization)相关推荐

  1. Python中的浅复制(shallow copy)和深复制(deep copy)

    文章目录 python值管理方式 深复制与浅复制的使用及区别 近期杂事太多,博客一直没更新,9月最后一天了,总得写点吧 今天记一下以前碰到过,最近又碰到的问题:python的深复制和浅复制 神奇的py ...

  2. 神经网络中的权重初始化问题weight initialization problem in FNN

    个人论文完成笔记 ^ _ ^欢迎批评指正 本篇文章研究的是全连接的多层神经网络中的权重初始化问题,以8-20-30-1的MLP为实验对象.神经网络是一种要素间关联性极强的结构,从输入数据,输入数据的s ...

  3. C++直接初始化与复制初始化的区别深入解析

    首先:这是原文地址,这个哥们的文章解决了我的问题.谢谢这个哥们了.下面把原文地址放在这里: https://www.jb51.net/article/54773.htm C++中直接初始化与复制初始化 ...

  4. c++中int向量初始化_以不同的方式在C ++中初始化2D向量

    c++中int向量初始化 Prerequisite: Initialize 1D vector 先决条件: 初始化一维向量 Before discussing about the initializa ...

  5. oracle10g数据库复制,oracle -10g 中Duplicate 复制数据库

    oracle --10g 中Duplicate 复制数据库 本次实验通过duplicate命令,在本机环境中创建一个复制数据库.目标数据库为hongye.复制数据库为catdb. 环境别名设置: al ...

  6. C++直接初始化和复制初始化

    (1)复制初始化的基本原理 我们知道,对象在内存中的直接表象是在内存中占有一个一定大小的空间.分配空间是建立对象的第一步.但是刚刚分配的空间就像一个没有开垦的荒田,或者是前面对象占有之后留下来的残余, ...

  7. 关于git bush 中不能复制黏贴的问题

    如果你是一个新手的话,在你使用个git的过程中,你会发现git 竟然不能复制黏贴,这简直是完全不能忍受的事,复制黏贴可以大大的节省了我们敲代码的时间,特别是在github中clone别人的仓库到本地, ...

  8. java直接调用复制文件,java中文件复制的4种方式,java文件的复制

    java中文件复制的4种方式,java文件的复制 今天一个同事问我文件复制的问题,他一个100M的文件复制的指定目录下竟然成了1G多,吓我一跳,后来看了他的代码发现是自己通过字节流复制的,定义的字节数 ...

  9. python中深浅复制教程

    在python中,等号作用是引用对象地址对应的对象 python中的数据分为可变类型和不可变类型: 可变类型:可列表.字典 不可变数据类型:字符串String.浮点型Float.整型Int.元祖Tup ...

最新文章

  1. 简单介绍一下R中的几种统计分布及常用模型
  2. 坑爹的Python陷阱(避坑指南)
  3. R语言list.dirs函数获取目录列表实战
  4. React 头像插件 react-avatar-editor 的使用
  5. 【SpringMVC 之应用篇】 1_SpringMVC入门 —— 第一个 Spring MVC 程序
  6. [云炬创业管理笔记]第二章成为创业者讨论4
  7. 清华大学王晨阳:轻量级Top-K推荐框架及相关论文介绍
  8. tomcat的三种部署方式
  9. linux c账户安全性,linux c flash安全策略
  10. c语言二维数组赋值前面是行还是列,动态二维数组分配有问题啊 为什么行和列相同才能给数组赋值...
  11. SQL未能排它地锁定数据库以执行该操作解决
  12. python3常用模块_Python3 常用模块1
  13. 密码学专题 OpenSSL专题
  14. POJ 2406题解kmp算法的应用
  15. 类与对象(面向对象的编程语言java)
  16. 4 实型变量,字符型数据(常量和变量),字符串常量2021-01-25
  17. 通达信 移动平均算法_通达信擒龙攻防战法主图指标公式
  18. 11.Python初窥门径(函数名,可迭代对象,迭代器)
  19. PV操作与信号灯例子
  20. win10 + cuda9.0+pytorch安装

热门文章

  1. mysql索引下推原理_MySQL:好好的索引,为什么要下推?
  2. Mac安装redis与后台启动
  3. Ndarry 拉伸为一个list
  4. java arraylist add时默认调用tostring_Java基础知识之ArrayList知识点总结
  5. vue-router组件重用 路由切换时的问题
  6. linux 下安装chrome的rpm包
  7. 多线程,死锁,DeadLock
  8. A10 平板开发一硬件平台搭建
  9. 首页终于让百度放出来了
  10. DataGridView实现多维表头