首页
|
新闻
|
新品
|
文库
|
方案
|
视频
|
下载
|
商城
|
开发板
|
数据中心
|
座谈新版
|
培训
|
工具
|
博客
|
论坛
|
百科
|
GEC
|
活动
|
主题月
|
电子展
注册
登录
论坛
博客
搜索
帮助
导航
默认风格
uchome
discuz6
GreenM
»
MCU 单片机技术
» c++学习笔记(10.专题二经典问题解析)
返回列表
回复
发帖
发新话题
发布投票
发布悬赏
发布辩论
发布活动
发布视频
发布商品
c++学习笔记(10.专题二经典问题解析)
发短消息
加为好友
bingchentiao
当前离线
UID
852665
帖子
6999
精华
0
积分
3500
阅读权限
90
在线时间
215 小时
注册时间
2011-8-30
最后登录
2014-1-19
论坛元老
UID
852665
1
#
打印
字体大小:
t
T
bingchentiao
发表于 2013-12-26 17:32
|
只看该作者
c++学习笔记(10.专题二经典问题解析)
知识点
,
经典
本节知识点:1.malloc与free和new与delete的区别:
a.malloc和free是
库函数
,以
字节
为单位申请堆内存
b.new和delete是
关键字
,以
类型
为单位申请堆内存
c.malloc和free是单纯的对内存进行申请与释放,不负责初始化,对于基本类型new关键字可以选择对内存进行初始化也可以不初始化
d.
对于类类型new和delete还负责调用构造函数和析构函数的调用
示例代码:
[cpp]
view plain
copy
#include <iostream>
#include <malloc.h>
using
namespace
std;
class
test
{
private
:
int
a;
int
b;
public
:
int
c;
test(
int
a,
int
b)
{
this
->a = a;
this
->b = b;
c = 9;
cout << "a is "<< a <<endl;
cout << "b is "<< b <<endl;
}
};
int
main()
{
test *p =
new
test(1,2); //当使用new创建一个类的对象的时候 调用构造函数
test *q =
reinterpret_cast
<test*> (malloc(
sizeof
(test))); //使用malloc 不调用构造函数
cout << "q is " << q->c <<endl;
cout << "c is " << p->c <<endl;
return
0;
}
2.编译器对构造函数的调用: a.一般类给对象进行初始化的方式有三种,test t1(5); test t2 = 5; test t3 = test(5); 在现代编译器中他们三个是等效的,但是从编译器内部来看是有区别的 b.
test t1(5)
是最简单直接的,他强制编译器直接调用test类的构造函数(
explicit无效
)。
test t2 = 5
有四个步骤,第一,默认情况下,字面量5的类型为int,因此5无法直接用于初始化test对象,第二,但是编译器在默认情况下可以自动调用构造函数(
explicit有效
),第三,于是编译器尝试调用test(int)生成一个临时对象,第四,最后调用拷贝构造函数test(const test& obj) 用临时对象给t2进行初始化(
explicit有效
)。
test t3 = test(5)
则是首先,手动调用test(int)构造函数(
explicit无效
),最后,编译器默认自动调用拷贝构造函数(
explicit有效
)
c.c++编译器会尝试各种手段让程序通过编译:
方式一:尽力匹配重载函数
方式二:尽力使用函数的默认参数
方式三:尽力尝试调用构造函数进行类型转换
d.
利用
explicit关键字
阻止编译器对构造函数的调用尝试
,代码如下:
[cpp]
view plain
copy
#include <iostream>
using
namespace
std;
class
test
{
private
:
int
a;
public
:
//explicit
test(
int
c)
{
cout << "test()" <<endl;
}
//explicit
test(
const
test& p)
{
cout << "test(const test& p)" <<endl;
}
~test()
{
cout << "~test()" <<endl;
}
};
int
main()
{
test a1(8); //阻止谁都没关系 因为这是最根本对 对象的初始化
test a2 = 8; //阻止构造函数 或者 阻止拷贝构造函数 都会造成这条语句的编译不过
test a3 = test(8); //阻止拷贝构造函数会造成这条语句的编译不过 因为构造函数是手动调用的
return
0;
}
e.
还有一个小问题,就是对于test t2 = 5 的这种方式,只能用于有test(int a)这样的构造函数的对象进行初始化。如果构造函数为test (int a, int b)这样,test t2 = (5, 4)是会编译出错的!!!
3.单例模式:
a.单例模式是
类的静态成员的一个很好的应用
,单例模式适用于
一个类只允许产生一个对象
的情况
b.
分析下单例模式:
既然这个类仅仅只能产生一个对象的话,所以
这个类的构造函数就应该是private属性的
,创建这类就不能是使用test t1(5)这样的语句了,就
只能使用函数
(有两种,
一种是静态成员函数
,
另一种是使用全局函数,这里面那个返回地址的变量也得是全局变量了
最好不要使用,因为这样就破坏了类的封装
),成员函数不可以的原因是:
没有对象无法调用成员函数
。函数中使用
new关键字
,new这个类,然后
将new出来的新地址返回
,这里面就需要一个static的静态成员变量来保存这个地址,
在这种情况下必须使用静态成员变量
,因为这个变量即
要在类中使用(
应该定义在类的前面或类中
)
,而且这个变量的类型
还是这个类的类型或指针类型(
应该定义在类的后面或类中
)
,
要返回给其他函数使用这个变量应该是静态类型的(
static属性
)
。所以说,在满足上面三种情况下,就要使用静态成员变量!!!
示例代码:
[cpp]
view plain
copy
#include <iostream>
using
namespace
std;
class
test
{
private
:
static
test* tp;
test()
{
}
public
:
static
test* creat()
{
if
(NULL == tp)
{
cout << "hello" <<endl;
tp =
new
test;
}
return
tp;
}
};
test* test::tp = NULL;
int
main()
{
test* only = test::creat();
test* only1 = test::creat();
return
0;
}
4.函数对象的实现: a.无状态函数:函数的调用只与实参值相关
b.状态函数:函数的调用结果不仅与实参值相关还与之前的函数调用有关,就是有记忆功能的函数,其实就是利用static属性变量
示例代码:
[cpp]
view plain
copy
#include <cstdlib>
#include <iostream>
using
namespace
std;
int
fib1(
int
i)
{
int
a1 = 0;
int
a2 = 1;
int
ret = a2;
while
( i > 1)
{
ret = a2 + a1;
a1 = a2;
a2 = ret;
i--;
}
return
ret;
}
int
fib2()
{
static
int
a1 = 0;
static
int
a2 = 1;
int
ret = a2;
int
t = a2;
a2 = a2 + a1;
a1 = t;
return
ret;
}
int
main(
int
argc,
char
*argv[])
{
for
(
int
i=1; i<=10; i++)
{
cout<<fib1(i)<<endl;
}
for
(
int
i=1; i<=10; i++)
{
cout<<fib2()<<endl;
}
return
0;
}
注意:第一,fib1是以无状态函数的方式实现的,求解数列每一项时都会做重复的循环,时间复杂度为O(n)
第二,fib2是以状态函数的方式实现的,每调用一次就可以得到数列当前项的值,时间复杂度为O(1),
但是无法从头再来
c.
函数对象的实现:其实就是利用对象来模拟有状态函数,利用对象中的成员变量来代替static属性的变量,但是同样也不能回头,
代码如下:
[cpp]
view plain
copy
#include <cstdlib>
#include <iostream>
using
namespace
std;
int
fib1(
int
i)
{
int
a1 = 0;
int
a2 = 1;
int
ret = a2;
while
( i > 1)
{
ret = a2 + a1;
a1 = a2;
a2 = ret;
i--;
}
return
ret;
}
int
fib2()
{
static
int
a1 = 0;
static
int
a2 = 1;
int
ret = a2;
int
t = a2;
a2 = a2 + a1;
a1 = t;
return
ret;
}
class
Fib
{
private
:
int
a1;
int
a2;
public
:
Fib()
{
a1 = 0;
a2 = 1;
}
int
operator() ()
{
int
ret = a2;
int
t = a2;
a2 = a2 + a1;
a1 = t;
return
ret;
}
};
int
main(
int
argc,
char
*argv[])
{
cout<<"int fib1(int i)"<<endl;
for
(
int
i=1; i<=10; i++)
{
cout<<fib1(i)<<endl;
}
cout<<endl;
cout<<"int fib2()"<<endl;
for
(
int
i=1; i<=10; i++)
{
cout<<fib2()<<endl;
}
cout<<endl;
Fib fib;
cout<<"Fib fib;"<<endl;
for
(
int
i=1; i<=10; i++)
{
cout<<fib()<<endl;
}
cout<<endl;
return
0;
}
收藏
分享
评分
回复
引用
订阅
TOP
返回列表
电商论坛
Pine A64
资料下载
方案分享
FAQ
行业应用
消费电子
便携式设备
医疗电子
汽车电子
工业控制
热门技术
智能可穿戴
3D打印
智能家居
综合设计
示波器技术
存储器
电子制造
计算机和外设
软件开发
分立器件
传感器技术
无源元件
资料共享
PCB综合技术
综合技术交流
EDA
MCU 单片机技术
ST MCU
Freescale MCU
NXP MCU
新唐 MCU
MIPS
X86
ARM
PowerPC
DSP技术
嵌入式技术
FPGA/CPLD可编程逻辑
模拟电路
数字电路
富士通半导体FRAM 铁电存储器“免费样片”使用心得
电源与功率管理
LED技术
测试测量
通信技术
3G
无线技术
微波在线
综合交流区
职场驿站
活动专区
在线座谈交流区
紧缺人才培训课程交流区
意见和建议