《 C++深度剖析》学习日志十八——神秘的临时对象
2018-02-13 08:52
399 查看
下面我们来学习C++中最神秘的临时对象,那么临时对象是什么呢?#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);//得到一个临时对象,过了这一行,临时对象就析构了,这一行依旧等价于//Test(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
我们来解读一下程序意图:在Test()中以0作为参数调用Test(int i),目的是将成员变量mi的初始值设置为0.
但结果很出乎意料,mi为随机值。究竟哪里出错了呢?
下面我再提出三个问题:
*构造函数是否可以直接调用?
*是否可以在构造函数中调用构造函数?
*直接调用构造函数的行为是什么?
前两个问题的答案在上面的例子中得到了体现,那最后一个问题的答案是什么?
*直接调用构造函数将产生一个临时对象
* 临时对象的生命周期只有一条语句的时间
* 临时对象的作用域只在一条语句中
* 临时对象是C++中值得警惕的灰色地带
解决方案:#include<stdio.h>
class Test
{
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i)
{
init(i);
}
Test()
{
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}输出结果便是mi = 0了
通过下面这段代码,我们就能看清楚临时对象的生成与销毁了。#include<stdio.h>
class Test
{
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i)
{
printf("Test(int i)\n");
init(i);
}
Test()
{
printf("Test()\n");
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
printf("main begin\n");
Test().print();
Test(10).print();
printf("main end\n");
return 0;
}
直接调用构造函数产生临时对象,赋值完了之后临时对象被消除,说白了,没什么用,这个只是学习历程,请大家提高警惕,在工作中尽量避免临时对象的生成。编译器也会尽量减少临时对象的产生#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
Test t = Test(10);
return 0;
}
C++编译器会尽力杜绝临时对象的产生,因为临时对象会带来性能上的问题
上面那一句等价于Test t(10);
#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
Test func()//生成一个Test类的临时对象,并返回这个对象
{
return Test(20);
}
int main()
{
Test t = Test(10);
Test tt = func();//用生成的临时对象来初始化tt。但实际是编译器做出了优化
//==》Test tt = Test(20);==》Test tt = 20;
t.print();
tt.print();
return 0;
}
结果并没有调用拷贝构造函数,所以说编译器对其进行了优化。
小结
*直接调用构造函数将产生一个临时对象
*临时对象是性能的瓶颈,也是bug的来源之一
*现代C++编译器会尽力避开临时对象
*同时也需要人为的避开临时对象
以上资料均来自狄泰,群号:199546072,志同道合的朋友可以加我:
qq:335366243
微信:zhong_335366243
class Test
{
int mi;
public:
Test(int i)
{
mi = i;
}
Test()
{
Test(0);//得到一个临时对象,过了这一行,临时对象就析构了,这一行依旧等价于//Test(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}
我们来解读一下程序意图:在Test()中以0作为参数调用Test(int i),目的是将成员变量mi的初始值设置为0.
但结果很出乎意料,mi为随机值。究竟哪里出错了呢?
下面我再提出三个问题:
*构造函数是否可以直接调用?
*是否可以在构造函数中调用构造函数?
*直接调用构造函数的行为是什么?
前两个问题的答案在上面的例子中得到了体现,那最后一个问题的答案是什么?
*直接调用构造函数将产生一个临时对象
* 临时对象的生命周期只有一条语句的时间
* 临时对象的作用域只在一条语句中
* 临时对象是C++中值得警惕的灰色地带
解决方案:#include<stdio.h>
class Test
{
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i)
{
init(i);
}
Test()
{
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
};
int main()
{
Test t;
t.print();
return 0;
}输出结果便是mi = 0了
通过下面这段代码,我们就能看清楚临时对象的生成与销毁了。#include<stdio.h>
class Test
{
int mi;
void init(int i)
{
mi = i;
}
public:
Test(int i)
{
printf("Test(int i)\n");
init(i);
}
Test()
{
printf("Test()\n");
init(0);
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
printf("main begin\n");
Test().print();
Test(10).print();
printf("main end\n");
return 0;
}
直接调用构造函数产生临时对象,赋值完了之后临时对象被消除,说白了,没什么用,这个只是学习历程,请大家提高警惕,在工作中尽量避免临时对象的生成。编译器也会尽量减少临时对象的产生#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
int main()
{
Test t = Test(10);
return 0;
}
Test t = Test(10);这一句话我们来进行解读 1.生成临时对象 2.用临时对象初始化t对象 ==》调用拷贝构造函数但实际是这样子吗?
C++编译器会尽力杜绝临时对象的产生,因为临时对象会带来性能上的问题
上面那一句等价于Test t(10);
#include<stdio.h>
class Test
{
int mi;
public:
Test(int i)
{
printf("Test(int i) : %d\n", i);
mi = i;
}
Test()
{
printf("Test()\n");
mi = 0;
}
void print()
{
printf("mi = %d\n", mi);
}
~Test()
{
printf("~Test()\n");
}
};
Test func()//生成一个Test类的临时对象,并返回这个对象
{
return Test(20);
}
int main()
{
Test t = Test(10);
Test tt = func();//用生成的临时对象来初始化tt。但实际是编译器做出了优化
//==》Test tt = Test(20);==》Test tt = 20;
t.print();
tt.print();
return 0;
}
结果并没有调用拷贝构造函数,所以说编译器对其进行了优化。
小结
*直接调用构造函数将产生一个临时对象*临时对象是性能的瓶颈,也是bug的来源之一
*现代C++编译器会尽力避开临时对象
*同时也需要人为的避开临时对象
以上资料均来自狄泰,群号:199546072,志同道合的朋友可以加我:
qq:335366243
微信:zhong_335366243
相关文章推荐
- 《 C++深度剖析》学习日志十七——对象的销毁
- 《 C++深度剖析》学习日志十四——对象的构造(下)
- 《 C++深度剖析》学习日志十六——对象的构造顺序
- 《 C++深度剖析》学习日志十三——对象的构造(中)
- 《 C++深度剖析》学习日志二十五——操作符重载
- 《 C++深度剖析》学习日志二十一——类的静态成员函数
- 《 C++深度剖析》学习日志二十四——类中的函数重载
- 《 C++深度剖析》学习日志十九——经典问题解析二
- 《 C++深度剖析》学习日志二十——类的静态成员变量
- 深度探索c++对象模型 学习笔记 chapter2-1 default constructor
- 从汇编层面深度剖析C++基本对象布局 .
- 深度探索C++对象模型复习和学习 第六章:执行期语意学
- 深度探索C++对象模型复习和学习 第一章 关于对象 (Object Lessons)
- C++学习(四) 深度剖析堆与栈
- 深度探索C++对象模型复习和学习 第三章 Data 语义学(The Semantics of Data )
- 深度探索C++对象模型学习 之 C++构造函数语意学(一)
- C++中临时对象的学习笔记
- C/C++学习日志之一—面向对象和面向过程的基本理解
- 从汇编层面深度剖析C++基本对象布局
- 深度探索c++对象模型学习笔记