test1:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
void fuc(Copy_construction t)
{
cout << "fuc函数!\n";
}
void play_empty(void)
{
Copy_construction t1;//调用有默认实参的构造函数
Copy_construction t2 = t1;//调用拷贝构造函数
Copy_construction t3(t2);//调用拷贝构造函数
cout << "_________________\n";
fuc(t3);//实参初始化形参,调用拷贝构造函数
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
}

运行结果

test2:

修改fuc函数为引用或者指针类型。

 void fuc(Copy_construction *t)
{
cout << "fuc函数!\n";
} void fuc(Copy_construction &t)
{
cout << "fuc函数!\n";
} /*****引用或者指针类型调用时不会调用拷贝构造函数****/

test3:

匿名对象的出现:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
Copy_construction fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;//调用拷贝构造函数,生成匿名对象
}//运行到该处,先析构对象A,匿名对象是否析构要看怎么去接
//如下所示直接调用fuc()则此时匿名对象会被立即析构
void play_empty(void)
{
fuc();
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
} 如果直接显示调用构造函数,要看怎么去接这个函数, Copy_construction(1);调用之后马上执行析构匿名对象, Copy_construction  T= Copy_construction(1);不会马上析构还会转正。

test4:

修改fuc函数的返回类型为引用或者指针:

 Copy_construction *fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return &A;
} Copy_construction &fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;
} /********返回类型为指针或者引用不会调用拷贝构造函数*********/

test5:

改变接匿名对象的方式:

 #include<iostream>
using namespace std;
class Copy_construction {
public:
Copy_construction(int a = )
{
this->a = a;
cout << "这是有默认参数的构造函数!\n";
}
Copy_construction(const Copy_construction &obj)
{
cout << "这是拷贝构造函数!\n";
a = obj.a;
}
~Copy_construction()
{
cout << "一个对象被析构了!\n";
}
private:
int a;
};
Copy_construction fuc(void)
{
cout << "fuc函数!\n";
Copy_construction A;
return A;//调用拷贝构造函数,产生匿名对象
}//析构对象A,根据下面代码的接匿名对象的方式,
//此时匿名对象不仅不会马上析构,还会转正成为对象B
//从c++设计哲学上来说,这也是提高效率的一种方式,这样的设计是合理的,因为你想创建对象B,我就不用再新开辟内存了,直接用之前的匿名对象代替
void play_empty(void)
{
Copy_construction B=fuc();//这里不会调用拷贝构造函数,匿名对象直接转正了
cout << "匿名对象转正!\n";
}
int main()
{
play_empty(); cout << "hello world!\n";
return ;
}

test6:

再改变接匿名对象的方式,重写play_empty()函数:

void play_empty(void)
{
Copy_construction B;
B= fuc();
cout << "匿名对象不会转正!\n";
} //如上所示代码,此时对象B会开辟内存,在用返回的匿名对象赋值给B,将会在赋值完成之后立即析构匿名对象,这个时候匿名对象不会转正。

summary:以下情况会调用拷贝构造函数

1.直接初始化和拷贝初始化时

2.将一个对象作为实参传递给一个非引用或非指针类型的形参时

3.从一个返回类型为非引用或非指针的函数返回一个对象时

4.用花括号列表初始化一个数组的元素或者一个聚合类(很少使用)中的成员时。

c++之拷贝构造函数调用时机的更多相关文章

  1. C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象

    1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...

  2. C++ //构造函数调用规则 //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) //析构函数(空实现) //拷贝函数(值拷贝) //2.如果我们写了有参构造函数 编译器就不会提供默认构造函数 但是会提供拷贝构造函数 //3.如果我们写了拷贝函数 编译器就不再提供 默认 有参 构造函数

    //构造函数调用规则 #include <iostream> using namespace std; //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) ...

  3. C++派生类的拷贝构造

    一. 概述 通过几个简单的实验,回顾下派生类中拷贝构造的相关知识. 环境:Centos7 64位, g++ 4.8.5 在继承中,构造器与析构器均没有被继承下来.拷贝构造,也是一种构造,也没有被继承下 ...

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

    之所以要把它们放在一起,是因为在使用C/C++类语言的时候,很容易混淆这几个概念(对Java来说完全没有这样的问题,表示Javaor完全没有压力). 先建立一个测试类(包含.h和.cpp) //~ P ...

  5. 拷贝构造和拷贝赋值、静态成员(static)、成员指针、操作符重载(day06)

    十七 拷贝构造和拷贝赋值 浅拷贝和深拷贝 )如果一个类中包含指针形式的成员变量,缺省的拷贝构造函数只是复制了指针变量的本身,而没有复制指针所指向的内容,这种拷贝方式称为浅拷贝. )浅拷贝将导致不同对象 ...

  6. 【面试】C++类中的相关函数【构造,拷贝构造,析构,友元】

    构造函数:值的初始化,可带参数,无返回值,可重载,可存在多个 析构函数:释放对象内存空间,无参数,无返回值,不可重载,只能存在一个 拷贝构造函数:拷贝对象,其形参必须是引用 1.空类会默认添加哪些东西 ...

  7. C++ //构造函数的分类及调用 //分类 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 //按照类型分类 普通构造 拷贝构造

    1 //构造函数的分类及调用 2 //分类 3 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 4 //按照类型分类 普通构造 拷贝构造 5 6 #include <iostream ...

  8. c++拷贝构造和编译优化

    #include <iostream> using namespace std; class MyClass { public: MyClass(); MyClass(int i); My ...

  9. java初始化构造函数调用顺序

    类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值:  (2)调用父类构造函数:  (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式:  (4)调用本身构造函数. 例子 ...

随机推荐

  1. 【Linux】echo命令

    用途 echo是用于终端打印的基本命令 说明 只需要使用带双引号的文本,结合echo命令就可以将文本打印在终端. [root@localhost test]# echo "Hello Wor ...

  2. JavaScript中的闭包(closure)

    闭包的特性 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收  闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露,主要用于私有的方法和变 ...

  3. awk 取列后对数值进行判断取出大于1的数值

    [root@dataline-prod nginx]# tail -2 access.log 122.238.119.177 - - [26/Oct/2018:18:20:25 +0800] &quo ...

  4. .net连接MySQL的方法

    摘自:http://www.cnblogs.com/huayangmeng/archive/2011/04/06/2006866.html 最近要用C#做一个东西,连接之前项目的数据库(用MySQL建 ...

  5. HDUOJ----(1084)What Is Your Grade?

    关键是自己没有读懂题目而已,不过还好,终于给做出来了...... What Is Your Grade? Time Limit: 2000/1000 MS (Java/Others)    Memor ...

  6. Java虚拟机学习 - 对象内存分配与回收 ( 5 )

    对象优先在Eden上分配 大多数情况下,对象优先在新生代Eden区域中分配.当Eden内存区域没有足够的空间进行分配时,虚拟机将触发一次 Minor GC(新生代GC).Minor GC期间虚拟机将E ...

  7. Python学习笔记014——迭代工具函数 内置函数enumerate()

    1 描述 enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 2 语法 enumerate(sequ ...

  8. android LinearLayout设置selector不起作用解决

    设置方法 : android:background="@drawable/fen_selector" 如果只有这个的话,是不起作用的.还必须加上: android:clickabl ...

  9. linux ---性能监控(工具)

    linux服务器性能监控-nmon Nmon 是一个分析aix和linux性能的免费工具,出自IBM,其采集的数据通过nmon_analyser生成报表 一.下载 官网下载地址 百度网盘 二.运行和使 ...

  10. 深度解析(一六)Floyd算法

    Floyd算法(一)之 C语言详解 本章介绍弗洛伊德算法.和以往一样,本文会先对弗洛伊德算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 弗洛伊德 ...