c++之拷贝构造函数调用时机
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++之拷贝构造函数调用时机的更多相关文章
- C++ //拷贝构造函数调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象 //2.值传递的方式给函数参数传值 //3.值方式返回局部对象
1 //拷贝构造函数调用时机 2 3 4 #include <iostream> 5 using namespace std; 6 7 //1.使用一个已经创建完毕的对象来初始化一个新对象 ...
- C++ //构造函数调用规则 //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) //析构函数(空实现) //拷贝函数(值拷贝) //2.如果我们写了有参构造函数 编译器就不会提供默认构造函数 但是会提供拷贝构造函数 //3.如果我们写了拷贝函数 编译器就不再提供 默认 有参 构造函数
//构造函数调用规则 #include <iostream> using namespace std; //1.创建一个类,C++编译器会给每个类添加至少3个函数 //默认构造(空实现) ...
- C++派生类的拷贝构造
一. 概述 通过几个简单的实验,回顾下派生类中拷贝构造的相关知识. 环境:Centos7 64位, g++ 4.8.5 在继承中,构造器与析构器均没有被继承下来.拷贝构造,也是一种构造,也没有被继承下 ...
- C++ 构造函数、析构函数、拷贝构造、赋值运算符
之所以要把它们放在一起,是因为在使用C/C++类语言的时候,很容易混淆这几个概念(对Java来说完全没有这样的问题,表示Javaor完全没有压力). 先建立一个测试类(包含.h和.cpp) //~ P ...
- 拷贝构造和拷贝赋值、静态成员(static)、成员指针、操作符重载(day06)
十七 拷贝构造和拷贝赋值 浅拷贝和深拷贝 )如果一个类中包含指针形式的成员变量,缺省的拷贝构造函数只是复制了指针变量的本身,而没有复制指针所指向的内容,这种拷贝方式称为浅拷贝. )浅拷贝将导致不同对象 ...
- 【面试】C++类中的相关函数【构造,拷贝构造,析构,友元】
构造函数:值的初始化,可带参数,无返回值,可重载,可存在多个 析构函数:释放对象内存空间,无参数,无返回值,不可重载,只能存在一个 拷贝构造函数:拷贝对象,其形参必须是引用 1.空类会默认添加哪些东西 ...
- C++ //构造函数的分类及调用 //分类 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 //按照类型分类 普通构造 拷贝构造
1 //构造函数的分类及调用 2 //分类 3 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 4 //按照类型分类 普通构造 拷贝构造 5 6 #include <iostream ...
- c++拷贝构造和编译优化
#include <iostream> using namespace std; class MyClass { public: MyClass(); MyClass(int i); My ...
- java初始化构造函数调用顺序
类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值: (2)调用父类构造函数: (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式: (4)调用本身构造函数. 例子 ...
随机推荐
- 〖Linux〗Ubuntu 64位安装sqlite3_analyzer
1. 安装过程 -dev:i386 wget -c "http://www.sqlite.org/2013/sqlite-analyzer-linux-x86-3080200.zip&quo ...
- HDU 3316 My Brute(二维费用流)经典
My Brute Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- 判断URL是否支持断点续传?
#python #xiaodeng #判断URL是否支持断点续传? import urllib2 req = urllib2.Request('http://ftp.ubuntu.com/') req ...
- System.out.print实现原理猜解
我们往往在main中直接调用System.out.print方法来打印,但是其实就这简单的一步里面有很多的玄机,因为main是static的,所以只能调用static的函数,那么print是stati ...
- Linux下通用线程池的创建与使用
线程池:简单地说,线程池 就是预先创建好一批线程,方便.快速地处理收到的业务.比起传统的到来一个任务,即时创建一个线程来处理,节省了线程的创建和回收的开销,响应更快,效率更高. 在linux中,使用的 ...
- 开源大数据技术专场(下午):Databircks、Intel、阿里、梨视频的技术实践
摘要: 本论坛第一次聚集阿里Hadoop.Spark.Hbase.Jtorm各领域的技术专家,讲述Hadoop生态的过去现在未来及阿里在Hadoop大生态领域的实践与探索. 开源大数据技术专场下午场在 ...
- no !/ in spec
问题: 在学习hibernate的过程中涉及到hibernate.cfg.xml和hibernate.hbm.xml配置文件的编写,写完之后配置文件出现黄色感叹号,鼠标悬停在感叹号上时显示no !/ ...
- 【Linux】忘记root密码
常常有些朋友在配置好了Linux之后,结果root密码给他忘记去!要重新安装吗?不需要的,你只要以单人维护模式登陆即可更改你的root密码!下面以Redhat linux5为例 1)先将系统重新启动, ...
- RAC安装GI时运行root.sh脚本结果
第一节点运行root.sh脚本的结果: # /u01/app//grid/root.sh Performing root user operation for Oracle 11g The follo ...
- Shell习题100例
每日一文件 https://github.com/aminglinux/shell100/blob/master/ 要求:安照这样的日期格式(xxxx-xx-xx)每日生成一个文件,如生成的文件为20 ...