??xml version="1.0" encoding="utf-8" standalone="yes"?>
1、说明:(x)创徏数据?br />
CREATE DATABASE database-name
2、说明:(x)删除数据?br />
drop database dbname
3、说明:(x)备䆾sql server
--- 创徏 备䆾数据?device
USE master
EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat'
--- 开?备䆾
BACKUP DATABASE pubs TO testBack
4、说明:(x)创徏新表
create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..)
Ҏ(gu)已有的表创徏新表Q?
AQcreate table tab_new like tab_old (使用旧表创徏新表)
BQcreate table tab_new as select col1,col2... from tab_old definition only
5、说明:(x)删除新表
drop table tabname
6、说明:(x)增加一个列
Alter table tabname add column col type
注:(x)列增加后不能删除。DB2中列加上后数据类型也不能改变Q唯一能改变的是增加varcharcd的长度?br />
7、说明:(x)d主键Q?Alter table tabname add primary key(col)
说明Q删除主键:(x) Alter table tabname drop primary key(col)
8、说明:(x)创徏索引Qcreate [unique] index idxname on tabname(col....)
删除索引Qdrop index idxname
注:(x)索引是不可更改的Q想更改必须删除重新建?br />
9、说明:(x)创徏视图Qcreate view viewname as select statement
删除视图Qdrop view viewname
10、说明:(x)几个单的基本的sql语句
选择Qselect * from table1 where 范围
插入Qinsert into table1(field1,field2) values(value1,value2)
删除Qdelete from table1 where 范围
更新Qupdate table1 set field1=value1 where 范围
查找Qselect * from table1 where field1 like '%value1%' ---like的语法很_֦Q查资料!
排序Qselect * from table1 order by field1,field2 [desc]
LQselect count as totalcount from table1
求和Qselect sum(field1) as sumvalue from table1
q_Qselect avg(field1) as avgvalue from table1
最大:(x)select max(field1) as maxvalue from table1
最:(x)select min(field1) as minvalue from table1
11、说明:(x)几个高查询q算?br />
AQ?UNION q算W?
UNION q算W通过l合其他两个l果表(例如 TABLE1 ?TABLE2Qƈ消去表中M重复行而派生出一个结果表。当 ALL ?UNION 一起用时Q即 UNION ALLQ,不消除重复行。两U情况下Q派生表的每一行不是来?TABLE1 是来自 TABLE2?
BQ?EXCEPT q算W?
EXCEPT q算W通过包括所有在 TABLE1 中但不在 TABLE2 中的行ƈ消除所有重复行而派生出一个结果表。当 ALL ?EXCEPT 一起用时 (EXCEPT ALL)Q不消除重复行?
CQ?INTERSECT q算W?br />
INTERSECT q算W通过只包?TABLE1 ?TABLE2 中都有的行ƈ消除所有重复行而派生出一个结果表。当 ALL ?INTERSECT 一起用时 (INTERSECT ALL)Q不消除重复行?
注:(x)使用q算词的几个查询l果行必L一致的?
12、说明:(x)使用外连?
A、left outer joinQ?
左外q接Q左q接Q:(x)l果集几包括q接表的匚w行,也包括左q接表的所有行?
SQL: select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
BQright outer join:
叛_q接(双?Q结果集既包括连接表的匹配连接行Q也包括双接表的所有行?
CQfull outer joinQ?
全外q接Q不仅包括符可接表的匹配行Q还包括两个q接表中的所有记录?br />
二、提?br />
1、说明:(x)复制?只复制结?源表名:(x)a 新表名:(x)b) (Access可用)
法一Qselect * into b from a where 1<>1
法二Qselect top 0 * into b from a
2、说明:(x)拯?拯数据,源表名:(x)a 目标表名Qb) (Access可用)
insert into b(a, b, c) select d,e,f from b;
3、说明:(x)跨数据库之间表的拯(具体数据使用l对路径) (Access可用)
insert into b(a, b, c) select d,e,f from b in '具体数据? where 条g
例子Q?.from b in '"&Server.MapPath(".")&"\data.mdb" &"' where..
4、说明:(x)子查?表名1Qa 表名2Qb)
select a,b,c from a where a IN (select d from b ) 或? select a,b,c from a where a IN (1,2,3)
5、说明:(x)昄文章、提交h和最后回复时?br />
select a.title,a.username,b.adddate from table a,(select max(adddate) adddate from table where table.title=a.title) b
6、说明:(x)外连接查?表名1Qa 表名2Qb)
select a.a, a.b, a.c, b.c, b.d, b.f from a LEFT OUT JOIN b ON a.a = b.c
7、说明:(x)在线视图查询(表名1Qa )
select * from (SELECT a,b,c FROM a) T where t.a > 1;
8、说明:(x)between的用?between限制查询数据范围时包括了边界?not between不包?br />
select * from table1 where time between time1 and time2
select a,b,c, from table1 where a not between 数? and 数?
9、说明:(x)in 的用方?br />
select * from table1 where a [not] in ('?','?','?','?')
10、说明:(x)两张兌表,删除主表中已l在副表中没有的信息
delete from table1 where not exists ( select * from table2 where table1.field1=table2.field1 )
11、说明:(x)四表联查问题Q?br />
select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....
12、说明:(x)日程安排提前五分钟提?
SQL: select * from 日程安排 where datediff('minute',f开始时?getdate())>5
13、说明:(x)一条sql 语句搞定数据库分?br />
select top 10 b.* from (select top 20 主键字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主键字段 = a.主键字段 order by a.排序字段
14、说明:(x)?0条记?br />
select top 10 * form table1 where 范围
15、说明:(x)选择在每一lb值相同的数据中对应的a最大的记录的所有信?cMq样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成l排?{等.)
select a,b,c from tablename ta where a=(select max(a) from tablename tb where tb.b=ta.b)
16、说明:(x)包括所有在 TableA 中但不在 TableB和TableC 中的行ƈ消除所有重复行而派生出一个结果表
(select a from tableA ) except (select a from tableB) except (select a from tableC)
17、说明:(x)随机取出10条数?br />
select top 10 * from tablename order by newid()
18、说明:(x)随机选择记录
select newid()
19、说明:(x)删除重复记录
Delete from tablename where id not in (select max(id) from tablename group by col1,col2,...)
20、说明:(x)列出数据库里所有的表名
select name from sysobjects where type='U'
21、说明:(x)列出表里的所有的
select name from syscolumns where id=object_id('TableName')
22、说明:(x)列示type、vender、pcs字段Q以type字段排列Qcase可以方便地实现多重选择Q类似select 中的case?br />
select type,sum(case vender when 'A' then pcs else 0 end),sum(case vender when 'C' then pcs else 0 end),sum(case vender when 'B' then pcs else 0 end) FROM tablename group by type
昄l果Q?br />
type vender pcs
?sh)?A 1
?sh)?A 1
光盘 B 2
光盘 A 2
手机 B 3
手机 C 3
23、说明:(x)初始化表table1
TRUNCATE TABLE table1
24、说明:(x)选择?0?5的记?br />
select top 5 * from (select top 15 * from table order by id asc) table_别名 order by id desc
三、技?br />
1?=1Q?=2的用,在SQL语句l合时用的较?br />
"where 1=1" 是表C选择全部 "where 1=2"全部不选,
如:(x)
if @strWhere !=''
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere
end
else
begin
set @strSQL = 'select count(*) as Total from [' + @tblName + ']'
end
我们可以直接写成
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where 1=1 安定 '+ @strWhere
2、收~数据库
--重徏索引
DBCC REINDEX
DBCC INDEXDEFRAG
--收羃数据和日?br />
DBCC SHRINKDB
DBCC SHRINKFILE
3、压~数据库
dbcc shrinkdatabase(dbname)
4、{UL据库l新用户以已存在用户权限
exec sp_change_users_login 'update_one','newname','oldname'
go
5、检查备份集
RESTORE VERIFYONLY from disk='E:\dvbbs.bak'
6、修复数据库
ALTER DATABASE [dvbbs] SET SINGLE_USER
GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
GO
ALTER DATABASE [dvbbs] SET MULTI_USER
GO
7、日志清?br />
SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
@MaxMinutes INT,
@NewSize INT
USE tablename -- 要操作的数据库名
SELECT @LogicalFileName = 'tablename_log', -- 日志文g?br />
@MaxMinutes = 10, -- Limit on time allowed to wrap log.
@NewSize = 1 -- 你想讑֮的日志文件的大小(M)
-- Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size
FROM sysfiles
WHERE name = @LogicalFileName
SELECT 'Original Size of ' + db_name() + ' LOG is ' +
CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' +
CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
(DummyColumn char (8000) not null)
DECLARE @Counter INT,
@StartTime DATETIME,
@TruncLog VARCHAR(255)
SELECT @StartTime = GETDATE(),
@TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'
DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName)
AND (@OriginalSize * 8 /1024) > @NewSize
BEGIN -- Outer loop.
SELECT @Counter = 0
WHILE ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
BEGIN -- update
INSERT DummyTrans VALUES ('Fill Log')
DELETE DummyTrans
SELECT @Counter = @Counter + 1
END
EXEC (@TruncLog)
END
SELECT 'Final Size of ' + db_name() + ' LOG is ' +
CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
FROM sysfiles
WHERE name = @LogicalFileName
DROP TABLE DummyTrans
SET NOCOUNT OFF
8、说明:(x)更改某个?br />
exec sp_changeobjectowner 'tablename','dbo'
9、存储更改全部表
CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
@OldOwner as NVARCHAR(128),
@NewOwner as NVARCHAR(128)
AS
DECLARE @Name as NVARCHAR(128)
DECLARE @Owner as NVARCHAR(128)
DECLARE @OwnerName as NVARCHAR(128)
DECLARE curObject CURSOR FOR
select 'Name' = name,
'Owner' = user_name(uid)
from sysobjects
where user_name(uid)=@OldOwner
order by name
OPEN curObject
FETCH NEXT FROM curObject INTO @Name, @Owner
WHILE(@@FETCH_STATUS=0)
BEGIN
if @Owner=@OldOwner
begin
set @OwnerName = @OldOwner + '.' + rtrim(@Name)
exec sp_changeobjectowner @OwnerName, @NewOwner
end
-- select @name,@NewOwner,@OldOwner
FETCH NEXT FROM curObject INTO @Name, @Owner
END
close curObject
deallocate curObject
GO
10、SQL SERVER中直接@环写入数?br />
declare @i int
set @i=1
while @i<30
begin
insert into test (userid) values(@i)
set @i=@i+1
end
记存储q程中经常用到的本周Q本月,本年函数
Dateadd(wk,datediff(wk,0,getdate()),-1)
Dateadd(wk,datediff(wk,0,getdate()),6)
Dateadd(mm,datediff(mm,0,getdate()),0)
Dateadd(ms,-3,dateadd(mm,datediff(m,0,getdate())+1,0))
Dateadd(yy,datediff(yy,0,getdate()),0)
Dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))
上面的SQL代码只是一个时间段
Dateadd(wk,datediff(wk,0,getdate()),-1)
Dateadd(wk,datediff(wk,0,getdate()),6)
是表示本周旉D?
下面的SQL的条仉?是查询旉D在本周范围内的:
Where Time BETWEEN Dateadd(wk,datediff(wk,0,getdate()),-1) AND Dateadd(wk,datediff(wk,0,getdate()),6)
而在存储q程?
select @begintime = Dateadd(wk,datediff(wk,0,getdate()),-1)
select @endtime = Dateadd(wk,datediff(wk,0,getdate()),6)
多态, 事实上,q是 Template Method模式的关?/span>
2. 关于成员变量初始化顺序,几个有依赖关pȝ成员变量要初始化Q让写出构造函数?/strong>
在初始化列表中,成员变量的初始化序是其在类中声明顺序,而非列表中的序?br />
3. 写一个双链表?/span>
Struct ListNode
{
int nData;
ListNode* pPreviousNode;
ListNode* pNextNode;
}
一般链表都?x)有一个表头节点与指向表头节点的头指针Q?/span> 应该?x)提供列表接口?/span> 按此数据l构实现卛_?/span>
4. 写个is-a?/span>has-a?/span>
q个比较?/p>
Class Pet{};
Class Dog: public Pet{};
Class Boy{Pet* m_pPet;};
5. struct vs. class.
1)默认讉K属性, struct?/span>public, class?/span>private
2) 默认l承属性,struct?/span>public, class?/span>private
3)class可以用来声明模板参数Q?/span>struct不能
6. U?/span>8个小球的问题
没题
7. stl 里面vector的实玎ͼ内部I间的申请与分配Q?/span>
Vector中文名字是动态数l, 其内部数据结构就是一个数l, 但是在数l元素不够用的时候,p动态的重新分配Q?/span> 一般是现在大小的两倍, 然后把原数组的内Ҏ(gu)贝过厅R所以, 在一般情况下Q?/span> 其访问速度同一般数l, 只有在重新分配发生时Q?/span> 其性能才会(x)下降
8. struct /class的区?/span>
重复?/p>
9. Z么要?/span>struct
成员的默认属性不同,?/span>struct的话Q主要是作ؓ(f)数据的集合?/span>
10. 怎样使一?/span>class不能被实例化
1Q构造函数私有化Q?/span>2Q抽象类
11. U有l承?/span>publicl承的区别?/span>
U有l承Q?/span> 只承实玎ͼ不承实?/span> has-a
公有l承Q承接口与实现 is-a
12. void *p的问?/span>
不能++
13. 引用和指针的区别与联pR引用是否可以更?/span>
联系Q?/span> 支持多态,可以用来引用同一对象
区别Q指针可以ؓ(f)NULLQ?/span> 引用不可以; 指针可以重赋| 引用不可以;
14. windows~程基础Q线E与q程的区?/span>
E序是一pd静态的指o(h)序列
q程是程序的一ơ动态执行,q程其实是一个资源的容器Q包括一个私有的虚拟地址I间Q一些初始的代码与数据, 一些系l资源的句柄{?/span>
U程是一个进E中的执行体Q?/span> 一般包?/span>CPU寄存器状态,两个栈(内核模式Q用h式)(j)以及(qing)一?/span>TLS(Thread-Local Storage){?/span>
15. com+是否熟?zhn)?/span>
COM+?/span>COM技术的延与发展, 它包括了所?/span>COM的基本功能(Z接口的编E模型,基本lg服务Q,q组合了DCOMQɾlg技术g伸到了分布式领域Q和MTS-Microsoft Transaction ServerQ提供了服务器端的组件管理与配置理Q,q新增了一些服务:(x)负蝲qQ内存数据库Q事件模型,队列服务{,主要用于Windows DNA(Distributed interNet Application Architecture)三层l构的中间层?/span>
16. qC?/span>hash法
哈希表的目的是表查询插入修改能够辑ֈO(1)的算法复杂度Q?/span> 通过?/span>key~码来确定其存储地址来实玎ͼ 当不同的key得到相同的编码时Q便需要进行冲H检与处理Q一般方法有除留余数法, U性探法Q^Ҏ(gu)法Q?/span> q其无法真正达?/span>O(1)
17. 一?/span>32位的数据Q怎样扑ֈ最左边的一?/span>1Q?/span>
如果是在最左位Q这个数是负敎ͼ否则的话Q左UM位,看是否变成负敎ͼq是O(n)的算?/span>Q?/span> 也可以用一个模板去与,q不断改变这个模?/span>
O(n/2)的算法:(x)二分方式查找 Q?Q?/span>
18. 一?/span>4*4的格子,填入1~15 然后l个目标状态,怎样L索?br />
比如Q?br />
1 2 3 6
0 4 5 7
8 9 10 11
12 13 14 14
再给Z最l的状?Q随侉K可以Q?
0 表示一个空|可以UdQ有点像拼图Q?/strong>
人工的教材上用的应该是q个例子Q用A*法Q它既不是广度搜索,也不是深度搜索,而是一U启发式搜烦(ch)Q在q行下一步搜索之前,?x)用一个估价函数来对后面的节点评分Q?取评分最优的q行下一步搜索,如果找不到结果,回溯。对于本题,用曼哈顿距离作ؓ(f)评分标准是个不错的选择?/p>
19. l你100万个数据Q数据的值在0~65535之间 用最快的速度排序
多关键字基数排序MSD(MOST SIGNIFICANT DIGIT FIRST)
20. 如果我们的一个Y件品,用户回复_(d)(x)q行速度很慢Q你怎么处理Q?/span>
询问?/span>Workflow, 用户的硬件环?/span>
21. 八皇后问题,详述解法 Q?/span>八皇后问题说的是?/span>8*8国际象棋盘?/span>,要求在每一行放|一个皇?/span>,且能做到在竖方向,斜方向都没有冲突Q?/span>
回溯?/p>
22. kmp快速匹配算?/span> ---不算L的搞?/span>
普通的模式匚w法Q一旦不匚wQ模式串右移一位;但是其实Ҏ(gu)一直条Ӟ我们可以出应该向右Ud位以避免不必要的比较Q算法实现比较曲?/p>
23. 无向图中两点间最短\问题 ---伟大的_杰克斯拉法
假设一共有N个节点, 需要一个一l数l?/span>Previous[N]来记录前一个节点序P一个一l数l?/span>TotalLength[N]来记录从原点到当前节Ҏ(gu)短\径;一个二l数l?/span>Weights[N][N]来记录各点之间边的权?/span>(如果存在)Q?/span> 然后从源点到l点q行深度搜烦(ch)或广度搜索, 按以下规则:(x)搜烦(ch)到某个节?/span>bӞ假设其前一个节点ؓ(f)a, ?/span>TotalLength[a] + Weights[a][b]?/span>TotalLength[b]相比较,如果于TotalLength[b]Q?/span> ?/span>TotalLength[b] = TotalLength[a] + Weights[a][b], Previous[b] = a; 反之则不做Q何操作。这样到搜烦(ch)l束后, ?/span>Previous[N]数组中就能得到整条最短\径了
24. I间中Q意给两个向量Q求角^分线
先单位化Q?/span> 假设单位化后l果?/span>nv1, nv2, 则角q_Uؓ(f)(nv1+nv2) / 2
25. 什么是q?/span>
左右子树(wi)都是q?wi),且高度相差不?/span>1的有序二叉树(wi)
26. 哈夫曼编码问?/span>
理论基础:霍夫曼树(wi)是带权\径长度(WPLQ?/span>Weighted Path LengthQ最的二叉?wi),它不一定是完全二叉?wi),应该是权值大的外l点L节点最q的扩充二叉?wi)。霍夫曼~码是ؓ(f)了实现数据的最冗余编码,是数据压~学的基?/span> 它根据字W在甉|中出现的频率为权|构造霍夫曼?wi),左?f)0Q?/span> 右ؓ(f)1. 其有两个效果Q一是保证电(sh)文有最短的~码Q二是字W间不需要分隔符Q因Z同的字符必定有不同的开_(d)成ؓ(f)前缀~码Q?/span>
27. 有向图求?/span>
以该节点为源点与l点吗进行深度优先或q度优先搜烦(ch)
28. .l?/span>n个点Q求凸包问题
凸包(convex hull)是指一个最凸多边形,满q?/span>N个点都在多边形上Q或其内。算法描qͼ(x)
求出最右的那个点作为凸多边形的一个顶?/span>(P0)Q遍历其他所有点(Pi)Q?/span> 如果其他炚w在向?/span>P0Pi的同一侧,?/span>Pi也ؓ(f)凸多边Ş的顶炏V?/span>
29. 四则q算Q给一个前~表达式(波兰式)(j)或后~表达?/span>(逆L兰式)Q然后求解;l一个中~表达式)(j)
+*-CDBA -/EF---------------------> A+B*(C-D)-E/F 前缀-中缀
操作W进栈,一个变?/span>tmp放上一个中间操作数Q运结果)(j)Q遇到操作数(g)?/span>tmp是否为空Q?/span> I的话取两个操作敎ͼ不空的话取一个操作数Q另一个就?/span>tmp了,操作W出栈运,l果攑օtmp中,如果是操作符Q?/span>tmp清空
ABCD-*+EF/- ---------------------> A+B*(C-D)-E/F 后缀-中缀
操作数进栈,遇到操作W,两个操作数出栈,计算l果入栈
30. STL?/span>container有哪些?
序列容器Q?/span> vector, list, deque, bitset
兌容器: set, multiset, map, multimap
适配容器Q?/span>stack, queue, priority_queue
cd?/span>: string, valarray, bitset
扩展容器Q?/span>hash_set, hash_multiset, hash_map, hash_multimap
31. map中的数据存储方式是什么?
U黑?wi)?/span> 是一U^衡二叉搜索树(wi)Q?/span> h良好的最坏情况运行时_(d)l计性能好与AVL?wi)?j)
32. map?/span>hashmap有什么区别?
内部数据l构不同Q?/span> map是红黑树(wi)Q?/span>hashmap是哈希表
33. hashmap是标准库中的吗?
不是的,但在SGI stl?/span>vc2005中都提供了?/span>
34. vector中的eraseҎ(gu)?/span>algorithm?/span>remove有什么区别?
vector?/span>erase是真正删除了元素Q?/span> q代器访问不C?/span> algorithm中的remove只是单的把要remove的元素移C容器最后面QP代器q是可以讉K到的。因?/span>algorithm通过q代器操作,不知道容器的内部l构Q所以无法做到真正删除?/span>
35. object是什么?
h内部状态,以及(qing)操作?/span> 软g构造,用来表示真实存在Q物理上或概念上Q的对象
36. C++中如何阻止一个类被实例化Q?/span>
U虚函数Q构造函数私有化Q友元)(j)
37. 一般在什么时候构造函数被声明?/span>private呢?
singleton模式Q?/span> L某些操作Q如L拯构?/span>Q?/span>
38. 什么时候编译器?x)生成默认?/span>copy constructor呢?
用户没有自定?/span>copy constructorQ在代码中用到?/span>copy constructor;
39. 如果你已l写了一个构造函敎ͼ~译器还?x)生?/span>copy constructor吗?
如果我写的是copy constructor, 不会(x)
如果我写的不?/span>copy constructor, ?/span>38
40. Z么说如果一个类作ؓ(f)基类Q则它的析构函数要声明成virtual的?
因ؓ(f)Q如?/span>delete一个基cȝ指针Ӟ 如果它指向的是一个子cȝ对象Q那么析构函C׃(x)D无法调用子类析构函数Q从而导致资源泄霌Ӏ?/span> 当然Q另一U做法是基cL构函数设?/span>protected.
41. inline的函数和#define有什么区别?什么时候会(x)真的?/span>inlineQ什么时候不?x)呢Q?/span>
1) 宏是在预~译阶段单文本替代, inline在编译阶D实现展开
2)宏肯定会(x)被替代,而复杂的inline函数不会(x)被展开
3)宏容易出错(q算序Q,且难以被调试,inline不会(x)
4)宏不是类型安全,?/span>inline是类型安全的Q会(x)提供参数与返回值的cd(g)?/span>
当出C下情冉|inlinep|
函数size太大
inline虚函?/span>
函数中存在@环或递归
函数调用其他inline函数
42. 如果把一个类的成员函数写在类的声明中是什么意思?
inline此函?/span> Q?/span>inline?/span>templatecMQ?/span> 必须?/span>.h中实玎ͼ(j)
43. publicl承?/span>privatel承有什么架构上的区别?
public?/span>is-a的关p,l承接口与实?/span>
private?/span>has-a的关p?/span> Q只l承实现
44. 在多l承的时候,如果一个类l承同时l承?/span>class A?/span>class BQ?/span>class A?/span>B中都有一个函数叫foo()Q如何明的在子cM指出override哪个父类?/span>foo()Q?/span>
首先Q?/span>foo?/span>A,Bd该都是虚函数Q否则就直接覆盖了,没有这个问题了Q其ơ,q个问题从语法角度来看似乎是无法解决。因为我们不能改原有设计Q不然也没这个问题了:)Q?/span>,所有只好从extend来考虑Q?/span>
class EA: public class A
{
public:
virtual void foo(){fooA();}
private:
virtual void fooA() = 0;
}
class EB: public class B
{
public:
virtual void foo(){fooB();}
private:
virtual void fooB() = 0;
}
q样Q?/span> 我就可以override不同的函数来辑ֈq个目的?/span>
class AB: public EA, pubic EB
{
private:
virtual void fooA(){}
virtual void fooB(){}
}
45. 虚拟l承的语法是什么?
A
/ \
B C
\ /
D
class A{};
class B: virtual public A{};
class C: virtual public A{};
class D: public B, public C{};
46. 部分模版特例化和全部模版特例化有什么区别?
偏特化只使用于类模板Q而全特化适用与函数模板,cLѝ?/p>
偏特化的l果q是一个模板,而全特化的结果是一个具体的cd?/p>
47. ~一个函敎ͼ使一个单w表{|?/span>
应该是逆序?/p>
q个算法竟然花了我不少旉Q没有测试过的:(x)
48. 拆解一个整敎ͼ比如4,可以拆解?/span>4=3+1Q?/span>4=2+2Q?/span>4=2+1+1Q?/span>4=1+1+1+1
首先Q对一个数q行拆分后,可能又要Ҏ(gu)后一个因子进行拆分,所以要用递归Q其ơ,W?/span>n+1个因子是于{于W?/span>n个因子的Q再者,Ҏ(gu)后一个因子,我可以直接输出,也可以l拆分?/span>
法如下Q?br />
唉,老了Q这个小东西搞了?span>N久的。。。?/span>
49. 不用库函敎ͼ实现strcpy或?/span>memcpy{函?/span>
一个字节一个字节的拯dQ但是要考虑源内存与目标内存的重叠?/p>
50. 内联函数的作用和~点
把代码直接插入到调用的地方,可以减少函数调用的次敎ͼ但是?x)增加代码?/span>sizeQ还有,如果内联p|Q在每个调用?/span>obj里,都会(x)产生一份该函数的拷贝,q样既没有怎么减少代码?/span>sizeQ又没有减少函数的调用,赔了夫h又折c(din)。?/span>
51. 指针和引用的区别
指针可以不初始化Q引用必d始化
指针可以?/span>NULLQ而引用必d用一个实在的对象
指针可以重指向其他对象,引用一旦初始化Q便不再改变
52. 友元的意?/span>
使被声明为友元的函数或类可以讉K某个cȝ非共有成?/span>?/p>
53. 虚函数的意义 实现多?/p>
54. Overload, Overwrite, Override 各自的特点和意义 Overload: 函数重蝲(名字相同Q参C?/span>) OverwriteQ覆?/span> Override: 虚函数重?/span> 55. 头文件中?/span>ifndef/define/endif q什么用Q?/span> 防止该头文g被重复引?/span>?/span> 56. Q?/span>i nclude <filename.h> 和#i nclude “filename.h” 有什么区别? Q?/span>i nclude <filename.h>Q?/span> 从标准库路径d找该文gQ对?/span>VC来说Q应该还包括VC环境讄选项中的包含目录以及(qing)工程属性中指定的目?/span> Q?/span>i nclude “filename.h”Q先在当前目录查找,如果找不刎ͼ按上面那U方式寻?/span> 57. ?/span>C++ E序中调用被C ~译器编译后的函敎ͼZ么要?/span>extern “C”Q?/span> C++语言支持函数重蝲Q?/span>C 语言不支持函数重载。函数被C++~译后在库中的名字与C 语言的不同?/span>C++提供?/span>C q接交换指定W号extern“C”来解军_字匹配问?/span> 58. 一个类有基cR内部有一个其他类的成员对象,构造函数的执行序是怎样的? 先执行基cȝQ如果基cd中有虚基c,要先执行虚基cȝQ其他基cd按照声明zcL的顺序依ơ执行)(j)Q再执行成员对象的,最后执行自q?/span> 59. hqC个你熟?zhn)的设计模?/span> q个看你熟?zhn)什么了?/span>singleton最单了Q?/span>template method用的最多了Q?/span>bridge挺炫的,command吹吹undo,redo也不错。。。。?/span> 60. ?/span>UML 中,聚合(aggregation)和组?/span>(composition)有什么区别? 其实从名字就能分别出来了?/p>
聚合表示只是单的聚聚Q没什么本质的联系Q所以这些对象的生存旉也就没什么关pMQ?/p>
l合表示了更加紧密的一U关p,q些对象有着共同的生存期?/p>
一个典型的例子是孙(zhn)空Q手臂,金箍的关系。。。?/p>
61. C#?/span>C++除了语法上的差别以外Q有什么不同的地方Q?/span> C++是直接生成可执行代码Q?/span>C#是先生成中间代码Q等到第一ơ执行时Q才?/span>JITQ?/span>Just In TimeQ生成可执行的机器码?/span> q有是(1) c#有垃圾自动回收机ӞE序员不用担心对象的回收?/span>(2)c#严禁使用指针Q只能处理对象。如果希望用指针,则仅可在unsafe E序块中能用指针?/span>(3)c#只能单ѝ?/span>(4)必须通过cd讉K静态成员。不能像C++中那P通过对象讉K静态成员?/span>(5)在子cM重写父类的虚函数时必ȝ关键?/span>override,覆盖父类的方法要用关键字new 62. New delete?/span>malloc free 的区?/span> 对于c,New ?/span>delete?x)调用构造,析构函数 newQ?/span>delete都是能感知到cd的?/span>newq回一个制定的cdQ?/span>delete删除一个指定的cdQ从而不用给?/span>size。?/span>malloc?/span>free都是处理voidcd的。用时时必须l过强制cd转换?/span> 63. #define DOUBLE(x) x+xQ?/span>i = 5*DOUBLE(10)Q?/span>i是多?正确的声明是什么? I = 5*10+10 = 60 60 正确的声明是Q?/p>
#define DOUBLE(x) ((x)+(x)) 64. 有哪几种情况只能?/span>intialization list 而不能用assignment? 当类中含?/span>const?/span>reference 成员变量Q基cȝ构造函数都需要参敎ͼcM含有其他cȝ成员对象Q而该cȝ构造函数都需要参数?/span> 65. C++是不是类型安全的Q?/span> 不是。两个不同类型的指针之间可以强制转换?/span>C#是类型安全的?/span> 66. main 函数执行以前Q还?x)执行什么代码? 全局对象的构造函C(x)?/span>main 函数之前执行?/span> 67. 描述内存分配方式以及(qing)它们的区别?/span> Q?/span>1Q从静态存储区域分配。内存在E序~译的时候就已经分配好,q块内存在程序的整个q行期间都存在。例如全局变量Q?/span>static 变量?/span> Q?/span>2Q?/span> 在栈上创建。在执行函数Ӟ函数内局部变量的存储单元都可以在栈上创徏Q函数执行结束时q些存储单元自动被释放。栈内存分配q算内置于处理器的指令集?/span>用的?/span>cacheQ速度较快但容量较?yu)?/span> Q?/span>3Q?/span> 从堆上分配,亦称动态内存分配。程序在q行的时候用malloc ?/span>new 甌L多少的内存,E序员自p责在何时?/span>free ?/span>delete 释放内存。动态内存的生存期由我们军_Q用非常灵z,但问题也最多?/span> Q?Q文字常量区Q?如char* p = "hello, world"是一个例子,其内存也在程序编译的时候就已经分配好? 一个程序除了上面这些,q有一?5)E序代码Z?br />
68. 比较一?/span>C++?/span>static_cast ?/span> dynamic_cast 的区别?/span> Static_cast可以昑ּ的做一些自动{换,如一?/span>int, char一些基cd的{换,以及(qing)指针之间的{换。但是其不保证安全性?/span>Dynamic_cast主要作用其实在于把一个基cL针{化ؓ(f)子类指针Q因个基cL针真正指向的不一定是我们惌{换的cd的对象,所以{换可能失败,dynamic_cast能够知道p|而返?/span>NULLQ?/span>static_cast没那么聪明了,原因?/span>dynamic_cast?x)利?/span>rttiL找该转换是否可行.(耗费旉多点?/span>) 69. 当一个类A 中没有生命Q何成员变量与成员函数,q时sizeof(A)的值是多少Q如果不是零Q请解释一下编译器Z么没有让它ؓ(f)零?/span> 不ؓ(f)Ӟ不同的对象应该有不同的地址Q假设我声明一?/span>A的数l?/span>A a[2]Q如果ؓ(f)Ӟ那么a[0]?/span>a[1]的地址岂不相同?/span> 70. 已知两个链表head1 ?/span>head2各自有序Q请把它们合q成一个链表依然有序,要求用递归Ҏ(gu)q行?/span> 归ƈ排序Q应该比较简单。要注意的是如果一个链表ؓ(f)I,那么可以单的把另一个直接链q去了?br />
]]>
我爱你,不是因ؓ(f)你是一个怎样的hQ而是因ؓ(f)我喜Ƣ与你在一h的感觉?/p>
(2) No man or woman is worth your tears, and the one who is, won‘t make you cry.
没有人值得你流泪,值得让你q么做的Z?x)让你哭泣?/p>
(3) The worst way to miss someone is to be sitting right beside them knowing you can‘t have them.
失去某hQ最p糕的莫q于Q他q在w旁Q却犹如q在天边?/p>
(4) Never frown, even when you are sad, because you never know who is falling in love with your smile.
U늄伤心Q也不要愁眉不展Q因Z不知是谁?x)爱上你的笑宏Vl+cvz
(5) To the world you may be one person, but to one person you may be the world.
对于世界而言Q你是一个hQ但是对于某个hQ但是对于某个hQ你是他的整个世界?/p>
(6) Don‘t waste your time on a man/woman, who isn‘t willing to waste their time on you.
不要为那些不愿在你n上花Ҏ(gu)间的浪费你的时间?/p>
(7) Just because someone doesn’t‘t love you the way you want them to, doesn’t‘t mean they don‘t love you with all they have.
׃的h如果没有按你所希望的方式来׃Q那q不代表他们没有全心全意地爱你?/p>
(8) Don‘t try so hard, the best things come when you least expect them to.f.H0
不要着急,最好的M(x)在最不经意的时候出现?/p>
(9) Maybe God wants us to meet a few wrong people before meeting the right one, so that when we finally meet the person, we will know how to be grateful.;
在遇到梦中h之前Q上天也怼(x)安排我们先遇到别的hQ在我们l于遇见心A的h?数据恢复Q便应当心存感激?/p>
(10) Don‘t cry because it is over, smile because it happened.
不要因ؓ(f)l束而哭泣,微笑吧,Z的曾l拥有?
人所拥有的「最后的」(lastQ自由是Q我们可以选择我们的态度?/font>
有一位老hQ独自住在家里。他的儿奌回来照他。后来觉得最好还是住到老h院去比较好,因ؓ(f)他的眼睛已经完全看不见了?nbsp;
q入老h院的那一天,服务员牵着他的手告诉他Q房间的样子Q墙上的壁画Q窗户外面是一大片草地Q还有水池,q位老h回答_(d)真的好美Q我x在这里会(x)很开心。服务员瞪着他,一脸讶异的_(d)你什么都看不见,你怎么知道不呢Q?nbsp;
讲到q里Q你大概已经知道q故事想要说的是什么了Q?nbsp;
我们比那位老h的情况好多了。我们每天早上v来的时候有没有q么振奋Q这么积极?
办公室里的事好像永远都做不完。烦(ch)恼的事不知道Z么L那么多。房子、R子、小孩的学业Q今天的早饭该吃什么,q些事从未间断过Q就待会(x)儿出门,从R子开出去到抵辑ց车场Q至会(x)发三ơ火Q有人换车道没打信号灯;某段路塞车因为有人在路边q排停RQ再有就是ؕ按喇叭?nbsp;
惛_q里Q怪不得我们真的要做一选择。选择今天我要扑ֈ好的事Q还是要专注于烦(ch)恼的事。我们要选择感恩、宽容,抑或是要让抱怨、愤怒来折磨我。我们甚臛_以在今天选择兛_他hQ对他h感兴的Z(x)Q而不要让h?fn)惯性的在心头?nbsp;
30q前Q我对当时的工作非常不满Q时常抱怨,也多ơ口头叫嚯辞职。有一天一位其它部门的q长ȝ跟我_(d)永远不要因ؓ(f)q个工作不好而辞职,一定要因ؓ(f)另一个工作更好而辞职?br>
q二句话Ҏ(gu)很重要。媄(jing)响也很大。卅q后的今天,回想hQ他说的真的很有道理?nbsp;
现在的公司制度不好,下一个工作机构的体制多半也有~陷。现在的公司不公qI谁能保证新的公司一切都很合理公道。现在的公司有派p,天知道多公司有同样的权力斗争问题。跟现在的主处不好Q新工作的主就一定处得好吗?
因而换工作不是解决办法?br>
Ҏ(gu)的办法是改变态度。曾在集中营里住q,遭受qhcL(zhn)惨的折的奥地利心理学家Victor Frankelp为,人所拥有的「最后的」(lastQ自由是Q我们可以选择我们的态度。遭遇同L(fng)打击Q有的h选择的是l望Q有的h却选择了希望?nbsp;
朋友Q你选择的是什么?你准备怎样q这一天?
]]>
?STL 出现到现在已l这么多q了Q泛型算法是它的重要l成Q也是其中最“看v来很?#8221;的东西之一。然而在真实的程序设计中Q它往往成ؓ(f)E序员的心头一痛,因ؓ(f)一旦要?for_each Qaccumulate 之类的算法做一些稍微复杂一点的事情Q你׃(x)发现自己一个头变成两个大。即便是有了 boost::bind ?boost.lambda 的帮助,事情也仍然是扑朔qL(fng)Q求助于 comp.lang.c++ 虽然有用Q但是又何尝不是一U无奈。好了,现在我开始收集一些来?comp.lang.c++(.moderated) 的解{,希望日后对自己和他h有用?/p>
=================================================================================
预备问题Q算是第0个问题吧Q:(x)如何对一?STL 容器内的所有元素做某g事情Q?/p>
q取决于你要做什么,以及(qing)容器是什么。如果是 vector, list q样的容器,而你要把它们全部 cout 出来Q当前的标准 STL 解法是这L(fng)Q?/p>
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <string>
int main()
{
std::vector<std::string> vect;
vect.push_back("Hello");
vect.push_back(", ");
vect.push_back("world!");
std::copy( vect.begin(), vect.end(),
std::ostream_iterator<std::string>(std::cout) );
}
基本上,q算是一?#8220;q得?#8221;的方案,但是有点问题Q?br>1. 对于不熟(zhn)这个固定用法的人,cout 所有元素所首要考虑法?for_eachQ而不?copy Q事实上Qfor_each 也是最W合我们惯常逻辑的算法,因ؓ(f)在不使用 STL 法的时候,我们使用 for 循环来干qg事?br>2. 可读性不太良好,ostream_iterator 的用有?tricky Q而且也不能用于做其他的事情?/p>
我想熟?zhn)?boost 的h已经知道我下面要说什么了Q因为用 boost.lambda 做这件事情的非常漂亮:(x)
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
int main()
{
std::vector<std::string> vect;
vect.push_back("Hello");
vect.push_back(", ");
vect.push_back("world!");
std::for_each( vect.begin(), vect.end(), std::cout << _1 );
}
q和前面的程序一P输出我们熟?zhn)?Hello, world! 。直观、优雅而且Ҏ(gu)修改Q例如,如果你不是想要输出它们的|而是惌输出它们的长度,只需要做很少的修改:(x)
std::for_each( vect.begin(), vect.end(), std::cout << bind(&std::string::length, _1) << "\n" );
输出
5
2
6
bind 的作用是?lambda 表达式绑定到一个函数或者一个数据成员,在这里的意思,是对于每一?string Q都调用?length() Ҏ(gu)。_1 同样也可以成值的对象Q例如,先执?/p>
std::for_each( vect[0].begin(), vect[0].end(), _1 = bind(&toupper, _1) );
然后再把q些 string 输出Q你?x)得?/p>
HELLO, world!
因ؓ(f)那一句对 "Hello" 中的每一个字母调?toupper Qƈ把结果写回?/p>
=================================================================================
W一个问题:(x)如何对一?map 中所有的 key 或?value 做某件事情?
当然Q这q是取决于你要做的是什么。手?for 循环当然是万能的Q但是现在有了那么多的泛型算法,我们可以考虑其他的方案了Q这也是众多 C++ Gurus 推荐的思维方式Q如果是把所有的 value 全部 cout 出来Q用 boost.lambda 配合 for_each q是比较优雅的(虽然没有?vector ?list 那样的优雅)(j)Q?/p>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
int main()
{
std::map<int, std::string> strs;
strs[0] = "Hello";
strs[1] = ", ";
strs[2] = "world";
strs[3] = "!";
std::for_each( strs.begin(), strs.end(),
std::cout << bind(&std::map<int, std::string>::value_type::second, _1) );
}
q样的输出如我们所料,是 Hello, world! ?/p>
如果惌?key 也输出,道理是一L(fng)Q只需要这P(x)
std::for_each( strs.begin(), strs.end(),
std::cout << bind(&std::map<int, std::string>::value_type::second, _1) << '\t'
<< bind(&std::map<int, std::string>::value_type::first, _1) << '\n'
);
其结果是Q?/p>
Hello 0
, 1
world 2
! 3
因此Q对于一?map 中的 value 的操作往往可以依法炮制Q如果我们想要在其中L value ?“world" 的那一个元素,q且输出它的 key Q只需要一句话Q?/p>
std::cout <<
std::find_if( strs.begin(), strs.end(),
bind(&std::map<int, std::string>::value_type::second, _1) == "world" )->first;
STL 法 find_if 接受的第三个参数是一?prediate Q而生成这U(f)时的 functor 正是 lambda 的拿手好戏。上面的q句话也可以?boost::bind 来做Q只需要更?include ?using namespace Q代码本w无需更改。而如果你不借助于它们,你只有手写@环或者自己写一?predicate ?/p>
当情况变得复杂一些的时候,lambda 的用法也变得更加有趣了:(x)
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
class Person
{
public:
Person(){}
Person(const std::string& name) : name_(name){}
std::string Name()
{ return name_; }
private:
std::string name_;
};
int main()
{
std::map<int, Person> persons;
persons[123] = Person("Amy");
persons[234] = Person("Ralph");
persons[345] = Person("Simon");
persons[456] = Person("Maggie");
std::for_each( persons.begin(), persons.end(),
std::cout << bind(&std::map<int, Person>::value_type::first, _1) << '\t'
<< bind(&Person::Name,
bind(&std::map<int, Person>::value_type::second, _1)) << '\n'
);
std::cout << "Ralph's Id is: " <<
std::find_if( persons.begin(), persons.end(),
bind(&Person::Name,
bind(&std::map<int, Person>::value_type::second, _1)) == "Ralph" )->first;
}
q里 map ?value 元素不再是一个单U的 stringQ我们要输出的是q个 value ?Name() Q幸?lambda 的绑定可以联,所以我们仍然可以用 STL 法在一个表辑ּ之内搞定q些dQfor_each 输出 key ?value ?Name()Q?find_if 扑ֈ value ?Name() ?"Ralph" 的那一个元素,输出是这L(fng)Q?/p>
123 Amy
234 Ralph
345 Simon
456 Maggie
Ralph's Id is: 234
如果你想要把一个容器内的所有元素篏加v来,应该怎么办?
如果你想要把一个容器内的所有元素篏加v来,应该怎么办?
STL ?accumulate 可以让我们不必自己写循环Q?/p>
#include <iostream>
#include <functional>
#include <numeric>
#include <vector>
#include <string>
int main()
{
std::vector<int> vect;
vect.push_back(1);
vect.push_back(2);
vect.push_back(3);
vect.push_back(4);
std::cout << "Accumulate: " <<
std::accumulate( vect.begin(), vect.end(), 0, std::plus<int>());
}
输出Q?/p>
Accumulate: 10
其中?std::plus<int>() 可以省略Q因是3个参数的 accumulate 的默认行为?注意 accumulate 法是定义在 numeric 里面而不?algorithm 里面的?/p>
׃ accumulate ?plus 都是泛型的,所以如果你要篏加的不是 int 而是字符Ԍ对程序的修改也ƈ不大Q?/p>
#include <iostream>
#include <functional>
#include <numeric>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> vect;
vect.push_back("1");
vect.push_back("2");
vect.push_back("3");
vect.push_back("4");
std::cout << "Accumulate: " <<
std::accumulate( vect.begin(), vect.end(), std::string(""));
}
输出Q?br>Accumulate: 1234
不过Q如果?boost.lambda Q这个问题会(x)有一些很好看又容易理解的解法Q?/p>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
//#include <boost/bind.hpp>
using namespace boost::lambda;
//using namespace boost;
int main()
{
std::vector<std::string> vect;
vect.push_back("1");
vect.push_back("2");
vect.push_back("3");
vect.push_back("4");
std::string result;
std::for_each( vect.begin(), vect.end(), result += _1);
std::cout << result;
}
输出Q?br>1234
q里要借用变量 result Q在q个E序中显得多了几行,但是我们调用 accumulate 的目的也往往是把l果攑ֈ一个变量中Q这L(fng)话,使用 boost.lambda 反而会(x)漂亮一些?/p>
在上面的E序中,另一个丑陋的地方是 vector 的初始化Qؓ(f)了把 1, 2, 3, 4 放进 vect 里面Q我们居然要调用 push_back 4ơ!不过Q?boost.lambda 好得多了?/p>
std::vector<int> vect(10);
int i = 0;
std::for_each( vect.begin(), vect.end(), _1 = ++var(i) );
q里有两个地方值得注意Q?br>1. 现在必须?vect 的声明中指出其大,否则 for_each 对一个空容器可是什么也不会(x)?br>2. 必须使用 ++var(i) Q而不?++i 。var 在这里的作用是强q?lazy evaluation Q也是让变量在被用到的时候在求|如果?++i Q你?x)得C个装?0??vect Q而不是装?-10?/p>
=================================================================================
许多问题遇到 map 都会(x)变得复杂hQ如果想要把一?map 中所有的 key 或?value 累加hQ该怎么办呢Q这个时候已l不能直接?accumulate 了,?boost.bind 可以办到Q做法是q样的:(x)
#include <iostream>
#include <algorithm>
#include <numeric>
#include <map>
#include <string>
#include <boost/bind.hpp>
using namespace boost;
int main()
{
std::map<int, std::string> persons;
persons[123] = "Amy";
persons[234] = "Ralph";
persons[345] = "Simon";
persons[456] = "Maggie";
std::cout << std::accumulate( persons.begin(), persons.end(), 0,
bind(std::plus<int>(), _1, bind(&std::map<int, std::string>::value_type::first, _2)) )
<< std::endl;
std::cout << std::accumulate( persons.begin(), persons.end(), std::string(),
bind(std::plus<std::string>(), _1, bind(&std::map<int, std::string>::value_type::second, _2)) )
<< std::endl;
}
输出Q?/p>
1158
AmyRalphSimonMaggie
办是办到了,但是q_而论Q的算不上是漂亮。连l的 bind q不比自己写的@环更让h头晕。boost.lambda 也要用到 bind Q然而可以清晰许多:(x)
#include <iostream>
#include <algorithm>
#include <numeric>
#include <map>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
int main()
{
std::map<int, std::string> persons;
persons[123] = "Amy";
persons[234] = "Ralph";
persons[345] = "Simon";
persons[456] = "Maggie";
int iresult = 0;
std::string sresult;
std::for_each( persons.begin(), persons.end(),
iresult += bind(&std::map<int, std::string>::value_type::first, _1)
);
std::for_each( persons.begin(), persons.end(),
sresult += bind(&std::map<int, std::string>::value_type::second, _1)
);
std::cout << iresult << std::endl;
std::cout << sresult << std::endl;
}
输出和上面的一P(x)
1158
AmyRalphSimonMaggie
有了它的帮助Q即侉K接层ơ再增加一层,也不?x)有太多困难Q假如你?map q不直接存储 string Q而是存储 Person 对象Q而它们的名字要通过 Name() Ҏ(gu)来取得,代码只需要稍微的修改Q?/p>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <map>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
using namespace boost::lambda;
class Person
{
public:
Person(){}
Person(const std::string& name) : name_(name){}
std::string& Name()
{ return name_; }
private:
std::string name_;
};
int main()
{
std::map<int, Person> persons;
persons[123] = Person("Amy");
persons[234] = Person("Ralph");
persons[345] = Person("Simon");
persons[456] = Person("Maggie");
std::string result;
std::for_each( persons.begin(), persons.end(),
result += bind(&Person::Name, bind(&std::map<int, Person>::value_type::second, _1))
);
std::cout << result;
}
输出Q?/p>
AmyRalphSimonMaggie
上次提到qؓ(f)容器生成数据的问题,我给出的?boost.lambda 的方法是
上次提到qؓ(f)容器生成数据的问题,我给出的?boost.lambda 的方法是Q?/p>
std::vector<int> vect(10);
int i = 0;
std::for_each( vect.begin(), vect.end(), _1 = ++var(i) );
不错Q这样可以生成连l的数字Q也q算比较z,因ؓ(f)代码量不?x)随着容器的大而变化,不过Q如果要在容器内填入随机数呢Q其实比上面更简单,因ؓ(f) STL ?generate 法是设计来做q个的:(x)
std::vector<int> vect(10);
std::generate(vect.begin(), vect.end(), rand);
rand 是我们熟(zhn)的标准 C 库函敎ͼq样我们可以生成L数量的随机数了,不过q是有点不好的地方:(x)每次生成的序列都是一L(fng)Q因?rand 生成的是伪随机数。这个容易解冻I我们必须?seed 一下:(x)
std::vector<int> vect(10);
srand(time(NULL));
std::generate(vect.begin(), vect.end(), rand);
好了Q我们终于还是用了三行(其实是两行,声明 vector L必需的吧Q)(j)Q但是好Ҏ(gu)有了一个可用的Ҏ(gu)。回头看看,前面的连l整数问题也可以?generate 来做Q方法不a而喻Q?/p>
std::vector<int> vect(10);
int i = 0;
std::generate(vect.begin(), vect.end(), ++var(i));
好处?generate 本n更能说明q句话的用途,当然q个可能因h而异?/p>
我知道有Z定在问:(x)一定要两行么?一定要有一个初始变量么Q答案是可以没有Q但是要用到另外的算法,再加?boost.lambda 的协助。看看下面:(x)
std::vector<int> vect(10);
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = _1 + 1);
如果你现在把 vect 输出Q你?x)得刎ͼ?x)
0 1 2 3 4 5 6 7 8 9
乍看h不太好理解,我来慢慢解释?br>partial_sum 的第4个参数是一个双参数?functor Q在q里Qlambda 表达?_2 = _1 + 1 充当了这个角Ԍ它相当于
f(x, y) { y = x + 1; }
?partial_sum 呢?它把一个序列的 partial sum 送到l果序列中去Q例如如果输入一个数l?v[10] Q而输出是 r[10] Q那么它的计就?/p>
r[0] = v[0]
r[1] = f( r[0], r[1] )
r[2] = f( r[1], r[2] )
......
r[9] = f( r[8], r[9] )
而当我们?partial_sum 作用?vect 本nQ结果就成了
vect[0] = vect[0] // vect[0] = 0
vect[1] = (vect[1] = vect[0] + 1) // vect[1] = 1
vect[2] = (vect[2] = vect[1] + 1) // vect[2] = 2
......
vect[9] = (vect[9] = vect[8] + 1) // vect[9] = 9
你一定发现其中的问题所在了Q首先,我们必须依赖于编译器?vect[0] 初始化ؓ(f)0Q其ơ,vect[0] = vect[0] 是不可回避的。以我当前所惛_的,也只能这样了?/p>
推广一下,如果?_2 = _1 + 1 中的常数 1 换成另外的数字,我们可以用一句话得到?0 开始的{差数列Q例?/p>
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = _1 + 3);
得到的是
0 3 6 9 12 15 18 21 24 27
如果再发挥一Ҏ(gu)象力Q你可以构造出更复杂的 lambda 表达式,从而得到更复杂的数l(也许q里叫数列更好吧Q,例如
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2 * _1 + 1);
得到的是 2 ?n ơ方 - 1 数列
0 1 3 7 15 31 63 127 255 511
?STL 法中,adjacent_difference ?partial_sum 是逆运,因此Q上面的事情也可以用 adjacent_difference 来做Q只不过要把 lambda 表达式中的参C|换一下,例如要得?0, 3, 6... 的等差数列,只需?/p>
std::adjacent_difference(vect.begin(), vect.end(), vect.begin(), _1 = _2 + 3);
?2 ?n ơ方 - 1 数列也是同样道理
std::adjacent_difference(vect.begin(), vect.end(), vect.begin(), _1 = 2*_2 + 1);
如果你要生成倒序的数列呢Q当?dng)STL 法 reverse 可以z上用场Q不q也不要忘了 STL q有 reverse_iterator q回事,用它?yu)无需另外调用 reverse 了:(x)
std::partial_sum(vect.rbegin(), vect.rend(), vect.rbegin(), _2 = 2*_1 + 1);
得到
511 255 127 63 31 15 7 3 1 0
最后还要提醒大家不要忘了一个很有用?STL 法Q?random_shuffle 。它可以?Random access container 里面的值打乱,配合上面的数列生成,在很多场合是q行试 Q例如测试排序算法)(j) 的好工具。在我的机器上,下面两行
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
std::random_shuffle(vect.begin(), vect.end());
得到打ؕ以后的数列:(x)
255 1 511 3 0 31 127 7 15 63
=================================================================================
有了强大的生成机制作基础Q下面的实验也更加容易了。STL ?count_if ?find_if 都接受一?predicate 作ؓ(f)比较的依据,而这?predicate 往往非常单,以至于ؓ(f)它专门写一?functor 直不可接受。在W一里面已l展CZ?boost.lambda 生成临时的无?functor 的能力,q里再多说一炏V?/p>
下面先生?2^n - 1 的数l,然后扑և其中W一个大?00的数
std::vector<int> vect(10);
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
std::cout << *std::find_if(vect.begin(), vect.end(), _1 > 100);
输出?127 Q如我们所料。同样道理,如果?count_if Q则?x)得到大?00的数的个?/p>
std::cout << std::count_if(vect.begin(), vect.end(), _1 > 100);
输出?3 。注意细节:(x)find_if q回一?iterator Q所以在它之前有 * 解引用,?count_if 直接q回一个数字,无需解引用?/p>
与之cM的还?STL ?partition 法Q它Ҏ(gu)传入?predicate 对一个序列进行划分,predicate 得到 true 的将攑֜前面Q其余的攑֜后面Q返回的是那?#8220; 攑֜ 后面”的元素中的第一个,换言之就是分界点。下面的代码
std::vector<int> vect(10);
std::partial_sum(vect.begin(), vect.end(), vect.begin(), _2 = 2*_1 + 1);
std::cout << *std::partition(vect.begin(), vect.end(), _1 > 100) << std::endl;
std::for_each(vect.begin(), vect.end(), std::cout << _1 << " ");
输出?/p>
7
511 255 127 7 15 31 63 3 1 0
如果仔细观察Q还可以发现上面的输出有炚w题:(x)数列中原有的序Q?, 1, 3, 7...Q不复存在,q是因ؓ(f) partition q不是一个稳定排序的法Q它不保证排序结果保有原来的序。如果需要稳定排序,可以使用 stable_partition 。只需要更Ҏ(gu)序的那一句代码ؓ(f)
std::cout << *std::stable_partition(vect.begin(), vect.end(), _1 > 100) << std::endl;
l果?/p>
0
127 255 511 0 1 3 7 15 31 63
当然Q如果你q记得大学里的算法理论,q道它们在效率上是有点区别的,partition 的复杂度保证?O(n) Q具体地说是保证不超q?n/2 ơ交换;?stable_partition 在最好情况下?O(n) Q最差情况则辑ֈ O(n*log(n)) ?/p>
Z说一下,上面的几件简单的事情Q用标准?STL 法都可以办刎ͼ只不q实在是……面目可憎Q?/p>
std::cout << *std::partition(vect.begin(), vect.end(),
std::bind2nd(std::greater<int>(), 100)) << std::endl;
q句代码做的事情和前面的 partition 一模一P但是C孰劣Q大家自有公断?/p>
L一些时候,我们不能够借助?#8220;生成?#8221;的初始化Ҏ(gu)来给容器赋|例如我们已经有了一个数l,要把它作为初Dl一个容器,常规的做法已l深入h心了
L一些时候,我们不能够借助?#8220;生成?#8221;的初始化Ҏ(gu)来给容器赋|例如我们已经有了一个数l,要把它作为初Dl一个容器,常规的做法已l深入h心了Q?/p>
int init[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
std::vector<int> vect(init, init + sizeof(init)/sizeof(int));
通过两个 sizeof 来得到数l的大小?C 语言里面是很常见的,然而在 C++ 里面Q这即便不能UCؓ(f)丑陋Q也l对UC上是好。首先其可读性不好,其次它要q行一ơ除法来得到一个本来在~译期间q道的数字Q最后,它ƈ不是总能用的Q例如下面的例子Q?/p>
std::string strs[] = { "Amy", "Ralph", "Simon", "Maggie" };
现在Q你打算?"sizeof " 什么来除以 "sizeof" 什么?
其实Q经q了q么?C++ GP 的磨l,我们很容易就?x)想C个在~译期间得到静态数l大的办法Q模板偏特化是我们常用的武器Q在q里非常好用Q?/p>
template <class T>
struct ArraySize
{
static const unsigned int value = 0;
};
template <class T, int S>
struct ArraySize<T[S]>
{
static const unsigned int value = S;
};
p么简单!虽然它只对付一l数l,但是扩展它是很容易的。不q,模板参数只能为类型,而我们需要传入的是一个变量。好在在计算机科学里面,加一层抽象是可以解决M问题的,我们只要加一个模板函敎ͼC++ ?x)自动帮我们做类型推|(x)
template <class T>
unsigned int array_size(const T&)
{
return ArraySize<T>::value;
}
现在我们可以轻而易丄搞定那些数组了:(x)
int ints[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
std::vector<int> vint(ints, ints + array_size(ints));
std::string strs[] = { "Amy", "Ralph", "Simon", "Maggie" };
std::vector<std::string> vstr(strs, strs + array_size(strs));
std::for_each(vint.begin(), vint.end(), std::cout << _1 << " ");
std::cout << std::endl;
std::for_each(vstr.begin(), vstr.end(), std::cout << _1 << " ");
输出Q?/p>
2 3 5 7 11 13 17 19 23
Amy Ralph Simon Maggie
Z说一下,?boost.type_traits 里面有一个类g ArraySize 的工P叫做 extent Q它更加强大Q可以对付多l数l,不过是否值得Zq个而把 boost.type_traits 包含到工E里面去q读者自己抉择了?/p>
=================================================================================
容器的初始化是如此的常见Q以至于 boost 提供了一?assign 库来化这些操作。boost.assign 大量利用了重载的逗号和括h化赋值操作,提供了甚x用数l更加简z的语法Q?/p>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/std/list.hpp>
using namespace boost::assign;
int main()
{
std::vector<int> vint;
vint += 2,3,5,7,11,13,17,19,23;
std::vector<std::string> vstr;
vstr += "Amy","Ralph","Simon","Maggie";
std::list<std::string> lstr;
lstr += "Amy","Ralph","Simon","Maggie";
std::for_each(vint.begin(), vint.end(), std::cout << _1 << " ");
std::cout << std::endl;
std::for_each(vstr.begin(), vstr.end(), std::cout << _1 << " ");
std::cout << std::endl;
std::for_each(lstr.begin(), lstr.end(), std::cout << _1 << " ");
}
q行q个E序Q输Z前面的大致相同,但是我们注意到初始化更加z了Q而且也不需要额外的I间来存储数l,对于各种cdQ都能够以统一的方式来初始化,真是妙不可言。有的?assign 的作者在文档中还Ҏ(gu)引用?Bjarne Stroustrup 的话作ؓ(f)引子Q?/p>
There appear to be few practical uses of operator,().
Bjarne Stroustrup, The Design and Evolution of C++
q也许就?C++ 最大的力之一Q你无法预料它可以办C什么?/p>
下面关于 map 的例子也使用 boost.assign Q可以看到重载的括号l我们带来了多少方便?/p>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/assign/list_of.hpp>
using namespace std;
using namespace boost::assign;
using namespace boost::lambda;
int main()
{
map<string,int> months;
insert( months )
( "january", 31 )( "february", 28 )
( "march", 31 )( "april", 30 )
( "may", 31 )( "june", 30 )
( "july", 31 )( "august", 31 )
( "september", 30 )( "october", 31 )
( "november", 30 )( "december", 31 );
map<int,string> persons = map_list_of
(2,"Amy")(3,"Ralph")
(5,"Simon")(7,"Maggie");
for_each( months.begin(), months.end(),
cout << bind(&map<string,int>::value_type::second, _1) << "\t"
<< bind(&map<string,int>::value_type::first, _1) << "\n"
);
cout << endl;
for_each( persons.begin(), persons.end(),
cout << bind(&map<int,string>::value_type::first, _1) << "\t"
<< bind(&map<int,string>::value_type::second, _1) << "\n"
);
}
输出Q?/p>
30 april
31 august
31 december
28 february
31 january
31 july
30 june
31 march
31 may
30 november
31 october
30 september
2 Amy
3 Ralph
5 Simon
7 Maggie
boost在vc2005中的~译出现codepage警告和DEPRECATED函数的解册日下载了一个VC2005 Express EditionQ用它来~译boostQ发现有不少的warning C4819Q说代码文g中有cp936无法表示的字W,q有是vc2005Ҏ(gu)的废弃的ANSI函数的错误,虽说不媄(jing)响编译,但是看着时不时出现的warningL让h心神不安Q还Ҏ(gu)掩盖其他的错误,如果是直接用cl~译Q只要加?wd4819 /D_CRT_SECURE_NO_DEPRECATE可以不昄q两个错误,但是大家都知道boost是用其Ҏ(gu)的boost.buildq行~译的,下面我就l出如何修改boost.build来抑制这两个错误的显C?/p>
boost.build分ؓ(f)v1和v2两个版本
v1Q?br>修改$(BOOST_ROOT)/tools/build/v1/vc-8_0-tools.jam
?/p>
flags vc - 8_0 C ++ FLAGS : / Zc:forScope ;
改ؓ(f)
flags vc - 8_0 C ++ FLAGS : / Zc:forScope / wd4819 / D_CRT_SECURE_NO_DEPRECATE ;
v2Q?br>cvs版本
修改$(BOOST_ROOT)/tools/build/v2/tools/msvc.jam
?/p>
# 8.0 adds some more options
一行的下方加上
flags msvc.compile CFLAGS $(condition) : / wd4819 / D_CRT_SECURE_NO_DEPRECATE ;
boost 1.33.1版本
?/p>
# 8.0 deprecates some of the options
if ! [ MATCH ^ ([ 67 ]. * ) : $(version) ]
{
flags msvc.compile CFLAGS $(condition) /< optimization > speed : / O2 ;
flags msvc.compile CFLAGS $(condition) /< optimization > space : / O1 ;
flags msvc.link.dll MANIFEST : " mt -manifest " ;
flags msvc.link.dll OUTPUTRESOURCE : " -outputresource: " ;
}
改ؓ(f)Q?/p>
# 8.0 deprecates some of the options
if ! [ MATCH ^ ([ 67 ]. * ) : $(version) ]
{
flags msvc.compile CFLAGS $(condition) : / wd4819 / D_CRT_SECURE_NO_DEPRECATE ;
flags msvc.compile CFLAGS $(condition) /< optimization > speed : / O2 ;
flags msvc.compile CFLAGS $(condition) /< optimization > space : / O1 ;
flags msvc.link.dll MANIFEST : " mt -manifest " ;
flags msvc.link.dll OUTPUTRESOURCE : " -outputresource: " ;
}