c++直接初始化和复制初始化 理解

看此文之前可以先看其他两个博主的文章

http://blog.****.net/ljianhui/article/details/9245661#comments

http://blog.****.net/hou09tian/article/details/70844690


下面的代码在GCC编译器和vs编译器的表现是不一样的

c++直接初始化和复制初始化 理解

GCC编译器表现如下图:

c++直接初始化和复制初始化 理解


c++直接初始化和复制初始化 理解

上面的代码在VS中并没有报错。

GCC编译器中运行会报错,错误在line25和26,原因是line18的private。

line26的错误很好理解,因为直接要调用复制构造函数。line25行的错误要用到下面的分析。

分析:


英文来自 http://en.cppreference.com/w/cpp/language/copy_initialization

  • If T is a class type, and the cv-unqualifiedversion of the type of other is not T or derived from T, or if T is non-classtype, but the type of other is a class type, user-defined conversion sequencesthat can convert from the type of other to T (or to a type derived from T if Tis a class type and a conversion function is available) are examined and thebest 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 aconverting constructor was used, is then used to direct-initializethe object.The last step is usually optimized out and the result of the conversion isconstructed directly in the memory allocated for the target object, but theappropriate constructor (move or copy) is required to be accessible even thoughit's not used. (until C++17)

对上文我理解的是,在直接初始化的时候等号右侧的值和左侧不同类型,那先寻找合适的转换构造函数,然后调用这个函数转换为一个临时对象(c++17标准之前),然后拿这个临时对象来直接初始化等号左侧的对象(可能是调用复制构造函数吧。。我也不确定)。上面也说了,最后一步通常被优化,就是不创建临时对象,将转换结果直接作用到等号右侧的内存区域吧。标准也说了,即使move和copy构造函数不使用,在优化的情况下也必须accessible(不能private或者delete等)。

在GCC中将复制构造函数声明为private引发了line25的错误,因为此时的复制构造函数不accessible。而VS并没有引发错误。

引用《STL源码分析》一句话 “GCC对C++语言特性的支持相当良好,在C++主流编译器中表现耀眼”。

而VS对c++标准一直支持的不那么好(可能微软对C++有着自己的理解和应用吧)。这可能也是为什么copy构造函数声明为private,编译在VS中也是通过的,虽然此时的copy构造函数并不accessible。

所以两种编译器表现的不同也是可以理解的。

总结:

由上面可知标准是标准,不同编译器对标准的实现是不同的。对于直接初始化和间接初始化很多编译器在底层的实现是一样的,是做了优化的,能不用临时对象就不用临时对象(为了更好的效率)。平时写程序还是按照标准好一点,不管编译器的底层是如何做的,按照标准总是好的。


后续找到更多关于直接初始化和拷贝初始化的最根本区别在更新此文