-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
699 lines (672 loc) · 186 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[effective stl]]></title>
<url>http://lennybai.cn/2016/12/30/effective-stl/</url>
<content type="html"><![CDATA[<h1 id="序"><a href="#序" class="headerlink" title="序"></a>序</h1><p> 使用c++不可避免的要去使用和钻研stl。effective stl是教我们如何有效(更安全,更具有运行效率)的去使用stl的书,让我们成为更高产的程序员。<br><a id="more"></a></p>
<p>术语</p>
<p>标准序列容器: vector string deque list<br>标准关联容器: set multiset map multimap</p>
<p>remove 算法描述:查找的得到第一个元素的位置,然后从此位置开始遍历容器,将后面的元素依次前移,跳过和value相同值的元素,也就是说,所有和value相同值的元素都会被覆盖,而其他的元素都会依次前移。最后remove返回”指向最后一个 ‘有用’ 元素的iterator”,但是在remove算法过程中,并没有修改原容器的size,以及end()。但是从逻辑角度看,最后的[ 从remove得到的iterator_result, 容器的结尾end() ) 这个区间里面的元素已经没有意义了。所以这些元素不应该属于该容器了。remove算法能做的仅此而已,并没有删除这些无用的元素。<br> 结论:移除容器里面的元素不应该使用remove算法,而是容器自己的方法erase()。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[Third Party Applications of WineHQ ]]></title>
<url>http://lennybai.cn/2016/12/28/Third-Party-Applications-of-WineHQ/</url>
<content type="html"><![CDATA[<h1 id="序"><a href="#序" class="headerlink" title="序"></a>序</h1><p> 工作需要,简单调研一下WineHQ相关的内容。主要是摘要记录,不做更多思考。</p>
<h1 id="一、概述"><a href="#一、概述" class="headerlink" title="一、概述"></a>一、概述</h1><p> Wine (“Wine Is Not an Emulator” 的首字母缩写)是一个能够在多种 POSIX-compliant 操作系统(诸如 Linux,Mac OSX 及 BSD 等)上运行 Windows 应用的兼容层。 Wine 不是像虚拟机或者模拟器一样模仿内部的 Windows 逻辑,而是將 Windows API 调用翻译成为动态的 POSIX 调用,免除了性能和其他一些行为的内存占用,让你能够干净地集合 Windows 应用到你的桌面。[1]</p>
<a id="more"></a>
<p> Wine 项目由 Bob Amstadt 于 1993 年发起,旨在寻求一种在 Linux 上运行 Windows 3.1 程序的办法。不久之后,Alexandre Julliard 开始接手领导 Wine 的开发,从此由他管理这个项目。 多年以来,随着 Windows API 和应用为了适应新硬件及软件而不断演变,Wine 也一直不断发展来支持新的特性,移植到更多其他系统,并且更加稳定,提供着更好的用户体验。[1]</p>
<p> 为了让WINE变得更强大并且更容易被使用,有很多第三方的应用对它进行支持和扩展,本文主要对官网列举出来的部分第三方应用进行简略说明。</p>
<h1 id="二、Wine第三方应用"><a href="#二、Wine第三方应用" class="headerlink" title="二、Wine第三方应用"></a>二、Wine第三方应用</h1><p> 在wine的官网列举出两大类三方软件:仍在维护的和不再更新的。在仍在维护的三方软件中,我们最耳熟能详的当然就是crossover。不过我们关注的重点是除它之外的软件,看能否发现一些独特的特性。</p>
<h2 id="gnome-exe-thumbnailer"><a href="#gnome-exe-thumbnailer" class="headerlink" title="gnome-exe-thumbnailer"></a>gnome-exe-thumbnailer</h2><p> 在ubuntu软件包中我们可以找到这个软件。同样可以通过apt-get gnome-exe-thumbnailer来进行安装。这个三方应用主要的作用是将windows的exe按照原有的图标进行显示。详细的说,比如我们常用的qq图标是一个小企鹅。而ubuntu默认会将exe识别为同一种类型文件而显示默认的类型图标。安装这个三方应用后,它会提取原有的window图标加以显示。更多可以查看<a href="https://www.youtube.com/watch?v=9YXhNNCSwv8" target="_blank" rel="external">这个视频</a>.</p>
<h2 id="q4wine"><a href="#q4wine" class="headerlink" title="q4wine"></a>q4wine</h2><p> q4wine是一个用来安装和管理wine程序的kde工具。我们可以用q4wine去安装程序。同样可以去管理wine安装的应用程序。更多效果可以查看<a href="https://www.youtube.com/watch?v=951nVQQJhks&t=244s" target="_blank" rel="external">这个视频</a>.</p>
<h2 id="Winetricks"><a href="#Winetricks" class="headerlink" title="Winetricks"></a>Winetricks</h2><p> winetricks整体上看起来更像是一个包依赖管理器。通过运行winetricks脚本,为wine应用提供相应的动态库支持。更多效果可以查看<a href="https://www.youtube.com/watch?v=tqrVR1QjDPQ" target="_blank" rel="external">这个视频</a>.</p>
<h1 id="三、其他"><a href="#三、其他" class="headerlink" title="三、其他"></a>三、其他</h1><p> 这些三方库都可以在github或者google code上找到相应的源码,如果想要深入了解,可以进行源码阅读。<br> 令人遗憾的是,这些三方库的参考文档并不丰富,所以想要了解,还是需要看看别人的使用视频或者亲身感受一下。</p>
<p> </p>
<hr>
<h1 id="3-参考文献"><a href="#3-参考文献" class="headerlink" title="3 参考文献"></a>3 参考文献</h1><ul>
<li>[1]: <a href="http://www.oschina.net/p/wine/?fromerr=eLEvCq6E" target="_blank" rel="external">wine中文社区</a></li>
<li>[2]: <a href="https://wiki.winehq.org/Third_Party_Applications" target="_blank" rel="external">WINEHQ</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-ReverseInteger]]></title>
<url>http://lennybai.cn/2016/12/21/leetcode-ReverseInteger/</url>
<content type="html"><![CDATA[<h3 id="Reverse-Integer"><a href="#Reverse-Integer" class="headerlink" title="Reverse Integer"></a><a href="https://leetcode.com/problems/reverse-integer/" target="_blank" rel="external">Reverse Integer</a></h3><p>Reverse digits of an integer.</p>
<blockquote>
<p>Example1: x = 123, return 321</p>
<p>Example2: x = -123, return -321</p>
</blockquote>
<a id="more"></a>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 本题其实思路很简单,我个人认为只是问题的考察点,应该是对人们对边界的认识。简单的翻转我们都能想到,通过按10取余来获取最后一位,通过除以10来进行移位。一定要记得考虑int的边界。</p>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"limits.h"</span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> <span class="function"><span class="keyword">int</span> <span class="title">reverse</span><span class="params">(<span class="keyword">int</span> x)</span> </span>{</div><div class="line"> <span class="keyword">long</span> <span class="keyword">long</span> result = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(x != <span class="number">0</span>)</div><div class="line"> {</div><div class="line"> result = result * <span class="number">10</span> + x % <span class="number">10</span>;</div><div class="line"> x = x/<span class="number">10</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> (result > INT_MAX || result < INT_MIN) ? <span class="number">0</span> : result ;</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> Solution s;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">123456</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">1000</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">1001</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">0</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">-123</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">-1234</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.reverse(<span class="number">1534236469</span>) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << <span class="number">9646324350</span>+<span class="number">1</span> << <span class="built_in">endl</span>;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[c++11条件变量]]></title>
<url>http://lennybai.cn/2016/12/20/c-11%E6%9D%A1%E4%BB%B6%E5%8F%98%E9%87%8F/</url>
<content type="html"><![CDATA[<p> 写了个条件变量的小程序。感觉还是挺方便的。<br><a id="more"></a><br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><map></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><thread></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><mutex></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><condition_variable></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><chrono></span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line">mutex m_mtxCv;</div><div class="line"></div><div class="line">condition_variable m_Cv;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span></div><div class="line">{</div><div class="line"> <span class="keyword">while</span>(<span class="literal">true</span>)</div><div class="line"> {</div><div class="line"> unique_lock<mutex> lk(m_mtxCv);</div><div class="line"> <span class="built_in">cout</span> << <span class="string">" 1 "</span> << <span class="built_in">endl</span>;</div><div class="line"> m_Cv.wait_for(lk,chrono::milliseconds(<span class="number">5000</span>));</div><div class="line"> <span class="built_in">cout</span> << <span class="string">" 2 "</span> << <span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">{</div><div class="line"> <span class="function">thread <span class="title">t</span><span class="params">(print)</span></span>;</div><div class="line"> <span class="keyword">while</span>(<span class="literal">true</span>)</div><div class="line"> { </div><div class="line"> <span class="built_in">cin</span>.get();</div><div class="line"> m_Cv.notify_one();</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>编译</p>
<blockquote>
<p>c++ test.cc -std=c++11 -lpthread</p>
</blockquote>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-LongestPalindromicSubstring]]></title>
<url>http://lennybai.cn/2016/12/20/leetcode-LongestPalindromicSubstring/</url>
<content type="html"><![CDATA[<h3 id="LongestPalidrmicSubstring"><a href="#LongestPalidrmicSubstring" class="headerlink" title="LongestPalidrmicSubstring"></a><a href="https://leetcode.com/problems/longest-palindromic-substring/" target="_blank" rel="external">LongestPalidrmicSubstring</a></h3><p>Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.<br><a id="more"></a></p>
<h3 id="example"><a href="#example" class="headerlink" title="example"></a>example</h3><blockquote>
<p>Input: “babad”</p>
<p>Output: “bab”</p>
<p>Note: “aba” is also a valid answer.</p>
<p>Input: “cbbd”</p>
<p>Output: “bb”</p>
</blockquote>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 这个题我的答案并不巧妙,只能说是完成了任务。不过还是要说一下注意点:</p>
<ol>
<li>对连续的相同字符的处理</li>
<li>如果a[p..q]是palidrmic串,如果a[p-1]=a[q+1],那么a[p-1..q+1]也是palidrmic串</li>
</ol>
<p> 在leetcode的discuss专栏里有很多出色的解答,希望大家移步讨论区去自行学习。</p>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">void</span> <span class="title">GetInitSbutString</span><span class="params">(<span class="built_in">string</span> s, <span class="keyword">int</span> n, <span class="keyword">int</span> &start, <span class="keyword">int</span>& end)</span></span></div><div class="line"> {</div><div class="line"> <span class="keyword">while</span>(start - <span class="number">1</span> >= <span class="number">0</span>)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( s.at(start - <span class="number">1</span> ) == s.at(n) )</div><div class="line"> start = start <span class="number">-1</span>;</div><div class="line"> <span class="keyword">else</span> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">while</span>(end + <span class="number">1</span> < s.length())</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( s.at(end+<span class="number">1</span>) == s.at(n) )</div><div class="line"> end = end+<span class="number">1</span>;</div><div class="line"> <span class="keyword">else</span> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">int</span> <span class="title">getSubstring</span><span class="params">(<span class="built_in">string</span> s, <span class="keyword">int</span>& start)</span></span></div><div class="line"> {</div><div class="line"> <span class="keyword">int</span> tempStart = start, tempEnd = start;</div><div class="line"></div><div class="line"> GetInitSbutString(s, start, tempStart, tempEnd);</div><div class="line"> <span class="keyword">while</span>( (tempStart - <span class="number">1</span> >= <span class="number">0</span> ) && (tempEnd + <span class="number">1</span> < s.length() ) )</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( s.at(tempStart<span class="number">-1</span>) == s.at(tempEnd+<span class="number">1</span>))</div><div class="line"> {</div><div class="line"> tempStart = tempStart - <span class="number">1</span>;</div><div class="line"> tempEnd = tempEnd + <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> start = tempStart;</div><div class="line"> <span class="keyword">return</span> tempEnd-tempStart +<span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="built_in">string</span> <span class="title">longestPalindrome</span><span class="params">(<span class="built_in">string</span> s)</span> </span>{</div><div class="line"> <span class="keyword">int</span> start = <span class="number">0</span>,length=<span class="number">0</span>;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>; i < s.length(); i++)</div><div class="line"> {</div><div class="line"> <span class="keyword">int</span> tempStart = i;</div><div class="line"> <span class="keyword">int</span> l = getSubstring(s,tempStart);</div><div class="line"> <span class="keyword">if</span> (length <= l)</div><div class="line"> {</div><div class="line"> length = l;</div><div class="line"> start = tempStart;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> s.substr(start, length);</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> Solution s;</div><div class="line"> <span class="built_in">string</span> temp = <span class="string">"babad"</span>;</div><div class="line"> <span class="built_in">cout</span> << s.longestPalindrome(temp) << <span class="built_in">endl</span>;</div><div class="line"> temp = <span class="string">"cbbd"</span>;</div><div class="line"> <span class="built_in">cout</span> << s.longestPalindrome(temp) << <span class="built_in">endl</span>;</div><div class="line"> temp = <span class="string">"aba"</span>;</div><div class="line"> <span class="built_in">cout</span> << s.longestPalindrome(temp) << <span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-MedianOfTwoSortedArrays]]></title>
<url>http://lennybai.cn/2016/12/19/leetcode-MedianOfTwoSortedArrays/</url>
<content type="html"><![CDATA[<h3 id="MedianOfTwoSortedArrays"><a href="#MedianOfTwoSortedArrays" class="headerlink" title="MedianOfTwoSortedArrays"></a><a href="https://leetcode.com/problems/median-of-two-sorted-arrays/" target="_blank" rel="external">MedianOfTwoSortedArrays</a></h3><p>There are two sorted arrays nums1 and nums2 of size m and n respectively.</p>
<p>Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).</p>
<a id="more"></a>
<h3 id="example"><a href="#example" class="headerlink" title="example"></a>example</h3><blockquote>
<p>nums1 = [1, 3]<br>nums2 = [2]</p>
<p>The median is 2.0</p>
<p>nums1 = [1, 2]<br>nums2 = [3, 4]</p>
<p>The median is (2 + 3)/2 = 2.5</p>
</blockquote>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 本体对时间复杂度有要求。当我看到这个题目的时候,有两点引起我的注意,第一个就是两个数组都是有序的,第二个就是时间复杂度为log(n)。这是我想到了归并排序。就这样我按照归并排序的思路完成了本题。</p>
<p>部分细节:</p>
<ol>
<li>中位数并不总是一个。</li>
<li>遍历数组不需要全部遍历。</li>
<li>注意归并排序的代码实现。</li>
</ol>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><limits.h></span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> <span class="function"><span class="keyword">double</span> <span class="title">findMedianSortedArrays</span><span class="params">(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums1, <span class="built_in">vector</span><<span class="keyword">int</span>>& nums2)</span> </span>{</div><div class="line"> <span class="keyword">int</span> size = nums1.size()+nums2.size();</div><div class="line"> <span class="keyword">int</span> mid1 = size/<span class="number">2</span>;</div><div class="line"> <span class="keyword">int</span> mid2 = mid1 - (size%<span class="number">2</span>==<span class="number">0</span>?<span class="number">1</span>:<span class="number">0</span>);</div><div class="line"> <span class="keyword">int</span> temp, mid1num=<span class="number">0</span>,mid2num=<span class="number">0</span>,i=<span class="number">0</span>,j=<span class="number">0</span>;</div><div class="line"> nums1.push_back(INT_MAX);</div><div class="line"> nums2.push_back(INT_MAX);</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">int</span> k = <span class="number">0</span> ; k < size; k++)</div><div class="line"> {</div><div class="line"> temp = <span class="number">0</span>;</div><div class="line"> <span class="keyword">if</span>( nums1[i] < nums2[j] )</div><div class="line"> {</div><div class="line"> temp = nums1[i];</div><div class="line"> i++;</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span></div><div class="line"> {</div><div class="line"> temp = nums2[j];</div><div class="line"> j++;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span>( k == mid2 )</div><div class="line"> {</div><div class="line"> mid2num = temp;</div><div class="line"> }</div><div class="line"> <span class="keyword">if</span>( k == mid1 )</div><div class="line"> {</div><div class="line"> mid1num = temp;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> (mid1num + mid2num) / <span class="number">2.0</span>;</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> Solution s;</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> nums1 = {<span class="number">1</span>,<span class="number">3</span>};</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> nums2 = {<span class="number">2</span>};</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> nums3 = {<span class="number">1</span>,<span class="number">2</span>};</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> nums4 = {<span class="number">3</span>,<span class="number">4</span>};</div><div class="line"></div><div class="line"> <span class="built_in">cout</span> << s.findMedianSortedArrays(nums1, nums2) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << s.findMedianSortedArrays(nums3, nums4) << <span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[ActiveMQ使用记录]]></title>
<url>http://lennybai.cn/2016/12/15/ActiveMQ%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p> 今天简单的浏览了一些招聘需求,其中对消息队列所需的技术要求一般都是”熟悉ActiveMQ”。虽然之前做项目,使用过celery+rabbitmq的异步消息机制。这里还是为了给自己的简历贴一些金,来上手练一下ActiveMQ的使用。</p>
<h1 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h1><h3 id="开发运行环境"><a href="#开发运行环境" class="headerlink" title="开发运行环境"></a>开发运行环境</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">> lennybai@lennybai~$ lsb_release <span class="_">-a</span></div><div class="line">> No LSB modules are available.</div><div class="line">> Distributor ID: Ubuntu</div><div class="line">> Description: Ubuntu 16.04.1 LTS</div><div class="line">> Release: 16.04</div><div class="line">> Codename: xenial</div></pre></td></tr></table></figure>
<a id="more"></a>
<p> 对于工具的使用,用心去研读一下官方文档还是很有必要的。在参考文献中我列出了官网的链接,感兴趣的朋友可以阅读一下。ActiveMQ的环境要求,在官方文档中指出为:JRE和JDK。当然我是个懒汉,在这里不太希望用源码去安装ActiveMQ。我是这么干的:</p>
<ol>
<li><p>安装java</p>
<blockquote>
<p>sudo add-apt-repository ppa:webupd8team/java<br>sudo apt-get update<br>sudo apt-get install oracle-java8-installer</p>
</blockquote>
</li>
<li><p>安装ActiveMQ</p>
<blockquote>
<p><a href="http://activemq.apache.org/download.html" target="_blank" rel="external">官网下载</a>并解压,在bin目录下运行自己系统相同的activemq程序,执行./activemq start</p>
</blockquote>
</li>
</ol>
<p> 在web控制台打开<a href="http://127.0.0.1:8161/admin/" target="_blank" rel="external">http://127.0.0.1:8161/admin/</a>。初始用户名:admin 密码:admin。[activemq_install_dir]/data/activemq.log”中可以查看运行日志。netstat -an | grep 61616可以查看端口运行情况。<br> activemq我认为比较好的有三点:开源,漂亮控制台和没有繁琐的配置。</p>
<h1 id="试用"><a href="#试用" class="headerlink" title="试用"></a>试用</h1><hr>
<h1 id="3-参考文献"><a href="#3-参考文献" class="headerlink" title="3 参考文献"></a>3 参考文献</h1><ul>
<li>[1]: <a href="http://activemq.apache.org/version-5-getting-started.html#Version5GettingStarted-DocumentOrganization" target="_blank" rel="external">ActiveMQ Document</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-longestSubStringWithOutRepeatingCharacters]]></title>
<url>http://lennybai.cn/2016/12/13/leetcode-longestSubStringWithOutRepeatingCharacters/</url>
<content type="html"><![CDATA[<h3 id="longest-substring-without-repeating-characters"><a href="#longest-substring-without-repeating-characters" class="headerlink" title="longest-substring-without-repeating-characters"></a><a href="https://leetcode.com/problems/longest-substring-without-repeating-characters/" target="_blank" rel="external">longest-substring-without-repeating-characters</a></h3><p>Given a string, find the length of the longest substring without repeating characters.</p>
<a id="more"></a>
<h3 id="example"><a href="#example" class="headerlink" title="example"></a>example</h3><blockquote>
<p>Given “abcabcbb”, the answer is “abc”, which the length is 3.</p>
<p>Given “bbbbb”, the answer is “b”, with the length of 1.</p>
<p>Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.</p>
</blockquote>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 阅读本题后,都会有大致的概念应该怎么去处理。大题思路就是从头到位遍历字符串,记录所有的没有出现重复字符的子字符串,并记录其长度。最后选出最大长度输出。这个思路理论上应该可以解决我们的问题,但是如何写出漂亮解答,还是需要我们稍作思考的。<br> 让我们再重新审阅一下这个题目。如果我们假设子字符串s[i..j]为无重复子字符串,其长度为l。如果s[j+1]也不存在在s[i..j]中,那么s[i..j+1]也是无重复子字符串,其长度更新为l+1。根据这种设计,我们完全可以套用动态规划来解决这个问题。(前面的文章有介绍)<br> 那么我们进而去丰富我们的动态规划设计:</p>
<ol>
<li>标记子字符串起点substringstart。若s[j+1]与s[i..j]中无重复字符,那么s[i..j+1]的子字符串起点也为i;如果与r(i≤r≤j)重复,则其起点变为r+1;</li>
<li>记录最大长度longest。当前长度[i..j]为j-i+1,与longest做比较,则其较大的更新longest。</li>
<li>因为使用hashmap来优化记录存储。</li>
</ol>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> <span class="function"><span class="keyword">int</span> <span class="title">lengthOfLongestSubstring</span><span class="params">(<span class="built_in">string</span> s)</span> </span>{</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> hashMap(<span class="number">256</span>, <span class="number">-1</span>);</div><div class="line"> <span class="keyword">int</span> longest = <span class="number">0</span>, subStringStart = <span class="number">0</span>;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < s.length(); i++)</div><div class="line"> {</div><div class="line"> subStringStart = subStringStart >= hashMap[s[i]] + <span class="number">1</span> ? subStringStart : hashMap[s[i]] + <span class="number">1</span>;</div><div class="line"> hashMap[s[i]] = i;</div><div class="line"> longest = longest >= i-subStringStart +<span class="number">1</span> ? longest : i - subStringStart + <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> longest;</div><div class="line"> }</div><div class="line"></div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> <span class="built_in">string</span> s1 = <span class="string">"abcabcbb"</span>;</div><div class="line"> <span class="built_in">string</span> s2 = <span class="string">"a"</span>;</div><div class="line"> <span class="built_in">string</span> s3 = <span class="string">"abc"</span>;</div><div class="line"> <span class="built_in">string</span> s4 = <span class="string">"aab"</span>;</div><div class="line"> Solution solution;</div><div class="line"> <span class="built_in">cout</span> << solution.lengthOfLongestSubstring(s1) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << solution.lengthOfLongestSubstring(s2) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << solution.lengthOfLongestSubstring(s3) << <span class="built_in">endl</span>;</div><div class="line"> <span class="built_in">cout</span> << solution.lengthOfLongestSubstring(s4) << <span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[算法导论-动态规划]]></title>
<url>http://lennybai.cn/2016/12/13/%E7%AE%97%E6%B3%95%E5%AF%BC%E8%AE%BA-%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/</url>
<content type="html"><![CDATA[<h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><p> 前面我们已经介绍了分治思想。分治思想是将问题划分为<strong>互不相交的子问题</strong>,递归的求解子问题,再将它们的解组合起来,求出原问题的解。这一篇文章我们将一起来讨论一下动态规划。它是算法中另一个重要的思想。 <br> 动态规划的思想与分治思想相反,动态规划是用于<strong>子问题重叠</strong>的情况,即不同的子问题具有相同的子子问题。在这种情况下,动态规划相对于分治算法的优势在于,分治算法会重复的计算本是相同的子子问题,导致运算时间的浪费,而动态规划则只会计算一次。<br> 动态规划常常用于解决最优解的问题。这类问题常常有很多可行的解,我们希望的是从这些解中找到最优解。<br><a id="more"></a></p>
<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p> 类似于分治算法的三个步骤,动态规划的思考和设计层面也具有四个步骤。</p>
<ol>
<li>刻画一个最优解结构</li>
<li>递归定义最优解的值</li>
<li>计算最优解的值,通常使用自底向上的方法</li>
<li>利用计算出来的信息构造最优解</li>
</ol>
<h1 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h1><p> 这里我们通过一个简单的例子对动态规划的思想进行一下实践。</p>
<h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><table>
<thead>
<tr>
<th>长度i</th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>8</th>
<th>9</th>
<th>10</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>价格Pi</strong></td>
<td>1</td>
<td>5</td>
<td>8</td>
<td>9</td>
<td>10</td>
<td>17</td>
<td>17</td>
<td>20</td>
<td>24</td>
<td>30</td>
</tr>
</tbody>
</table>
<p> 上述表格描述的是一个钢条公司的钢条长度和价格的关系。它们希望得到给定长度为n的钢条,如何切割才能达到利益最大化。</p>
<h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p> 我们用n表示钢条的长度,i表示切割的长度,Pi表示切割长度对应的收益,Rn代表长度为n的钢条对应的最大收益。<br> 则我们可以得出Rn=max(Pi + Rn-1)。这个推倒式的表明的是对于n长的钢条。进行i(i从1到n)的长度的切割,获得的切割收益与剩余收益的和。再从i=1到i=n中选取最大的值,就是该n长钢条能获取的最大收益。</p>
<h3 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h3><p> 动态规划有两种等价的实现方法,分别为带备忘的自顶向下法和自底向上法。带备忘的自顶向下法,是按照自然的递归形式编写过程,但是过程中会保存没格子问题的解。自底向上法则需要恰当的定义子问题的规模,使得任何子问题都只依赖更小的子问题求解。<br>下面列出两种实现的伪代码。</p>
<p>自顶向下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">MEMOIZED-CUT-ROD(p,n)</div><div class="line"> let r[0..n] be a new array</div><div class="line"> for i = 0 to n</div><div class="line"> r[i]=-∞</div><div class="line"> return MEMOIZED-CUT-ROD-AUX(p,n,r)</div><div class="line"></div><div class="line">MEMOIZED-CUT-ROD-AUX(p,n,r)</div><div class="line"> if r[n]≥0</div><div class="line"> return r[n]</div><div class="line"> if n== 0</div><div class="line"> q = 0</div><div class="line"> else q = -∞</div><div class="line"> for i = 1 to n</div><div class="line"> q = max(q, p[i] + MEMOIZED-CUT-ROD-AUX(p, n-i, r))</div><div class="line"> r[n]=q</div><div class="line"> return q</div></pre></td></tr></table></figure></p>
<p>自底向上:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">BOTTOM-UP-CUT-ROD(p,n)</div><div class="line"> let r[0..n] be a new array</div><div class="line"> r[0]=0</div><div class="line"> for j = 1 to n</div><div class="line"> q = -∞</div><div class="line"> for i = 1 to j</div><div class="line"> q=max(q,p[i]+r[j-i])</div><div class="line"> r[j]=q</div><div class="line"> return r[n]</div></pre></td></tr></table></figure></p>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-AddTwoNum]]></title>
<url>http://lennybai.cn/2016/12/12/leetcode-AddTwoNum/</url>
<content type="html"><![CDATA[<h3 id="AddTwoNum"><a href="#AddTwoNum" class="headerlink" title="AddTwoNum"></a><a href="https://leetcode.com/problems/add-two-numbers/" target="_blank" rel="external">AddTwoNum</a></h3><p>You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.</p>
<a id="more"></a>
<h3 id="example"><a href="#example" class="headerlink" title="example"></a>example</h3><blockquote>
<p>Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)<br>Output: 7 -> 0 -> 8</p>
</blockquote>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 思路不算复杂,就是按照我们正常的加法竖式计算的方式来完成此题就可以。需要注意的细节有两点:</p>
<ol>
<li>进位值</li>
<li>判断list结尾</li>
</ol>
<p> 关于进位值(程序中定义为extra变量)在本题中,如果是list最后两个数字相加的进位,往往会被忽略。第二点,两个list不一定是等长的,所以在遍历的过程中,需要对list结尾进行判断,防止运行时空指针错误。注意这两点,可能就可以正确完成本题了。</p>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">struct</span> ListNode {</div><div class="line"> <span class="keyword">int</span> val;</div><div class="line"> ListNode *next;</div><div class="line"> ListNode(<span class="keyword">int</span> x) : val(x), next(<span class="literal">NULL</span>) {}</div><div class="line">};</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> <span class="function">ListNode* <span class="title">addTwoNumbers</span><span class="params">(ListNode* l1, ListNode* l2)</span> </span>{</div><div class="line"> <span class="function">ListNode <span class="title">result</span><span class="params">(<span class="number">0</span>)</span></span>;</div><div class="line"> ListNode* tempResult = &result;</div><div class="line"> <span class="keyword">int</span> l1Value, l2Value, extra;</div><div class="line"> l1Value = l2Value = extra = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(l1 != <span class="literal">NULL</span> || l2 != <span class="literal">NULL</span> || extra != <span class="number">0</span>)</div><div class="line"> {</div><div class="line"> l1Value = (l1!=<span class="literal">NULL</span>)?l1->val : <span class="number">0</span>;</div><div class="line"> l2Value = (l2!=<span class="literal">NULL</span>)?l2->val : <span class="number">0</span>;</div><div class="line"> tempResult->next = <span class="keyword">new</span> ListNode((l1Value+l2Value+extra)%<span class="number">10</span>);</div><div class="line"> extra = (l1Value+l2Value+extra) / <span class="number">10</span>;</div><div class="line"></div><div class="line"> l1 != <span class="literal">NULL</span> ? l1 = l1->next : l1 = <span class="literal">NULL</span>;</div><div class="line"> l2 != <span class="literal">NULL</span> ? l2 = l2->next : l2 = <span class="literal">NULL</span>;</div><div class="line"> tempResult = tempResult->next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> result.next;</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> ListNode* l1 = <span class="keyword">new</span> ListNode(<span class="number">2</span>);</div><div class="line"> l1->next = <span class="keyword">new</span> ListNode(<span class="number">4</span>);</div><div class="line"> l1->next->next = <span class="keyword">new</span> ListNode(<span class="number">3</span>);</div><div class="line"></div><div class="line"> ListNode* l2 = <span class="keyword">new</span> ListNode(<span class="number">5</span>);</div><div class="line"> l2->next = <span class="keyword">new</span> ListNode(<span class="number">6</span>);</div><div class="line"> l2->next->next = <span class="keyword">new</span> ListNode(<span class="number">4</span>);</div><div class="line"> <span class="comment">//l2->next->next = new ListNode(7);</span></div><div class="line"></div><div class="line"> Solution s;</div><div class="line"> ListNode* result = s.addTwoNumbers(l1,l2);</div><div class="line"></div><div class="line"> <span class="keyword">while</span>(result)</div><div class="line"> {</div><div class="line"> <span class="built_in">cout</span> << result->val << <span class="built_in">endl</span>;</div><div class="line"> result = result->next;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[算法导论--分治策略]]></title>
<url>http://lennybai.cn/2016/12/12/%E7%AE%97%E6%B3%95%E5%AF%BC%E8%AE%BA-%E5%88%86%E6%B2%BB%E7%AD%96%E7%95%A5/</url>
<content type="html"><![CDATA[<h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><p> 算法中有两个非常重要的思想分别是:分治策略和动态规划。它们通常可以将处理复杂的问题,转化为处理N个相关的子问题。通过这种方式,给予人们清晰的思路的同时,降低处理问题的难度。这一篇文章我们来介绍分治策略,并给出几个经典的算法来进行展示。</p>
<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p> 分治策略中,往往是通过递归去求解问题,并在每层递归中应用如下三个步骤:</p>
<ol>
<li>分解:将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小。</li>
<li>解决:递归的求解子问题,如果子问题的规模足够小,则停止递归,直接求解。</li>
<li>合并:讲子问题的解组合成原问题的解。</li>
</ol>
<a id="more"></a>
<h1 id="算法举例"><a href="#算法举例" class="headerlink" title="算法举例"></a>算法举例</h1><p> 在上一篇文章里,我们看到的归并排序其实使用的就是分治思想。这里我们再列举两个常用的,并且使用分治思想的算法:堆排序和快速排序。</p>
<h2 id="堆排序"><a href="#堆排序" class="headerlink" title="堆排序"></a>堆排序</h2><p> 堆排序的时间复杂度为O(nlogn),并且所需的额外存储数量固定。堆通常使用数组进行存储,它可以被看成一个近似的完全二叉树,它的每一个节点对应着数组中的一个元素。接下来我们试着去实现堆排序。<br> 首先我们来理解一下最大堆。如果按照刚才我们所提到的,将堆看做成二叉树。那么如果是最大堆,其特点是A[PARENT(i)]>=A[i]。这个公示代表着,任何一个节点不大于其父节点。这里我们用伪代码表示一下父节点和左右子节点的关系。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">PARENT(i)</div><div class="line"> return [i/2]</div><div class="line">LEFT(i)</div><div class="line"> return 2i</div><div class="line">RIGHT(i)</div><div class="line"> return 2i+1</div></pre></td></tr></table></figure></p>
<p> 接下来我们讨论一下堆排序算法。堆排序的一个重要环节是调节堆。详细的说,比如我们目标是构建最大堆,在N个节点的树中总会有不满足最大堆要求的父子节点关系,那么我们就要进行调整。<br> 堆排序的第一个环节就是构建最大堆。这里我们假设某个节点的两个子节点都已经是最大树的根节点,在这种情况下,再对该节点进行调整是最容易的。所以我们构建最大堆的思路是先讲子树构建成最大堆,然后开始父节点构建。这样我们将会完成最大堆的构造。然而,这里大家一定要注意,最大堆构建完成并不代表着数组已经排序完成。比如(16,14,10,8,7,9,3)就是最大堆,但是并不是有序的。它只保证了其父节点不小于该节点。<br> 最后我们来完成排序工作。具体的步骤就是,讲根节点与最后一个节点交换,并从树种去除,然后对树进行调整。不断的迭代这个过程,完成最终的排序工作。<br> 这里开始为自己的表达能力感到捉急。我们还是来看伪代码吧。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">//第一步,调整堆</div><div class="line">MAX-HEAPIFY(A,i)</div><div class="line"> l = LEFT(i)</div><div class="line"> r = RIGHT(i)</div><div class="line"> largest = i</div><div class="line"> if l <= heapsize and A[l] > A[i]</div><div class="line"> largest = l</div><div class="line"> if r <= heapsize and A[r] > A[i]</div><div class="line"> largest = r</div><div class="line"> if largest != i</div><div class="line"> exchange(A[i],a[largest])</div><div class="line"> MAX-HEAPIFY(A,largest)</div></pre></td></tr></table></figure></p>
<p> 第一步,通过递归来调整以i为根节点的子树为最大堆。以此为基础,我们讲堆从子节点向上遍历,不断地调整子树为最大树来完成最大堆的构建。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">//第二步,构建最大堆</div><div class="line">BUILD-MAX-HEAP(A)</div><div class="line"> A.heapsize = A.length</div><div class="line"> for i = [A.length/2] downto 1</div><div class="line"> MAX-HEAPIFY(A,i)</div></pre></td></tr></table></figure></p>
<p> 在完成最大堆的构建之后,我们已经完成了堆排序最核心的两个步骤,那么我们现在完成堆排序。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">//堆排序</div><div class="line">HEAP-SORT(A)</div><div class="line"> BUILD-MAX-HEAP(A)</div><div class="line"> for i = A.length downto 2</div><div class="line"> exchange A[i] with a[i]</div><div class="line"> A.heapsize = A.heapsize-1</div><div class="line"> MAX-HEAPIFY(A,1)</div></pre></td></tr></table></figure></p>
<p> 锵锵锵锵,堆排序完成。</p>
<h2 id="快速排序"><a href="#快速排序" class="headerlink" title="快速排序"></a>快速排序</h2><p> 另一个使用分治思想的常用算法就是快速排序。快速排序的期望时间复杂度是O(nlogn)。但是最坏情况的时间复杂度又O(n*n)。虽然看起来最坏情况的时间复杂度很差,但是实际排序应用中它往往是最好的选择,因为它的平均性很好,而且O(nlogn)的常数因子非常小。<br> 快速排序的三步分治过程:</p>
<ol>
<li>分解: 将数组A[p..r],以A[q]为界换分为两个子数组,子数组可以为空,q可以自由选择。使得A[p..q-1]中的元素都小于A[q],A[q+1..r]中的元素都大于A[q]。</li>
<li>解决: 通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序</li>
<li>合并: 因为子数组都是原址排序,所以不需要合并操作:数组A[p..r]已经有序</li>
</ol>
<p> 来看具体的伪代码实现:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">PARTITION(A,p,r)</div><div class="line"> x = A[r]</div><div class="line"> i = p - 1</div><div class="line"> for j = p to r - 1</div><div class="line"> if A[j] <= x</div><div class="line"> i = i + 1</div><div class="line"> exchange A[i] with A[j]</div><div class="line"> exchage A[i+1] with A[r]</div><div class="line"> return i + 1</div></pre></td></tr></table></figure></p>
<p> 在快速排序中,PARTITION是非常关键的部分,它的作用有两个,第一个是选定界限值q,第二个就是对输入数组进行原址重排。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">QUICKSORT(A,p,r)</div><div class="line"> if p < r</div><div class="line"> q = PARTITION(A,p,r)</div><div class="line"> QUICKSORT(A,p,q-1)</div><div class="line"> QUICKSORT(A,q+1,r)</div></pre></td></tr></table></figure></p>
<p> 快速排序完成</p>
]]></content>
</entry>
<entry>
<title><![CDATA[leetcode-two sum]]></title>
<url>http://lennybai.cn/2016/12/09/leetcode-twosum/</url>
<content type="html"><![CDATA[<h3 id="twoSum"><a href="#twoSum" class="headerlink" title="twoSum"></a><a href="https://leetcode.com/problems/two-sum/" target="_blank" rel="external">twoSum</a></h3><p>Given an array of integers, return indices of the two numbers such that they add up to a specific target.</p>
<p>You may assume that each input would have exactly one solution.</p>
<a id="more"></a>
<h3 id="example"><a href="#example" class="headerlink" title="example"></a>example</h3><blockquote>
<p>Given nums = [2, 7, 11, 15], target = 9,</p>
<p>Because nums[0] + nums[1] = 2 + 7 = 9,<br>return [0, 1].</p>
</blockquote>
<h3 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h3><p> 本题思路并不难。可以从第一个数开始遍历,与后面的所有剩余的数字进行加法运算,如果符合预期则返回。否则继续遍历。这里有一个很明显的问题就是增加了很多不必要的运算。算法时间复杂度较高。<br> 一个很巧妙的算法是通过map存储已经遍历过的数字。key存储其值,value存储其索引。通过对数字从头到尾遍历。计算目标值(target-当前值),并到map中查找,如果存在则返回,若不存在,将当前值存储到map中继续遍历。这样只需遍历一边数组就可完成整个算法。</p>
<h3 id="coding"><a href="#coding" class="headerlink" title="coding"></a>coding</h3><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unordered_map></span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">class</span> Solution {</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> twoSum(<span class="built_in">vector</span><<span class="keyword">int</span>>& nums, <span class="keyword">int</span> target)</div><div class="line"> {</div><div class="line"> <span class="built_in">unordered_map</span><<span class="keyword">int</span>,<span class="keyword">int</span>> record;</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> result;</div><div class="line"> <span class="keyword">for</span>( <span class="keyword">int</span> i = <span class="number">0</span>; i < nums.size(); i++)</div><div class="line"> {</div><div class="line"> <span class="keyword">int</span> numberToFind = target - nums[i];</div><div class="line"> <span class="keyword">if</span>(record.find(numberToFind) != record.end())</div><div class="line"> {</div><div class="line"> result.push_back(record[numberToFind]);</div><div class="line"> result.push_back(i);</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line"> record[nums[i]]=i;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> Solution s;</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> test = {<span class="number">2</span>,<span class="number">7</span>,<span class="number">11</span>,<span class="number">15</span>};</div><div class="line"> <span class="keyword">int</span> target = <span class="number">9</span>;</div><div class="line"></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i : s.twoSum(test, target))</div><div class="line"> <span class="built_in">cout</span> << i << <span class="built_in">endl</span>;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="github"><a href="#github" class="headerlink" title="github"></a>github</h3><p><a href="https://github.com/geeklenny/leetcode" target="_blank" rel="external">github代码链接</a></p>
]]></content>
</entry>
<entry>
<title><![CDATA[编程珠玑]]></title>
<url>http://lennybai.cn/2016/12/06/%E7%BC%96%E7%A8%8B%E7%8F%A0%E7%8E%91/</url>
<content type="html"><![CDATA[<h1 id="一、绪论"><a href="#一、绪论" class="headerlink" title="一、绪论"></a>一、绪论</h1><p> 编程珠玑是一本很有影响力的书籍。它是作者对自己在长期的计算机程序设计实践中积累下来的宝贵经验的总结。行文生动形象,可读性高。在美国,它被作为低年级数据结构与算法的教材,同时,也作为高年级的算法辅助教材。它涵盖了算法课程和数据结构课程的大部分内容。不同于其他教材,他不强调单纯的从数学上分析,而是强调结合实际问题进行分析、应用和实现。话不多说,开卷有益。<br><a id="more"></a></p>
<h1 id="二、概述"><a href="#二、概述" class="headerlink" title="二、概述"></a>二、概述</h1><p> 这是第二次翻开本书。虽然被很多人推荐,但阅读一遍后,我并没有抓到什么重点。这次边读边记录,希望能够做到讲本书融会贯通。主要是记录为主,可能每一段都没有核心,也可能上下文没有逻辑性,强迫症或者性情暴躁者,慎读。</p>
<h3 id="准确的问题描述"><a href="#准确的问题描述" class="headerlink" title="准确的问题描述"></a>准确的问题描述</h3><p> 在程序员的日常工作中,更多的工作更像是通过程序解决问题的过程。所以更好的描述问题,或者说是自己能够对需求更准确的转化成为问题,会对后续的程序设计帮助十足。将复杂的问题简单化,模块化。同时,能否准确的描述问题,也决定这你是否将要解决一个“正确”的问题。<br> 一般情况下,对问题的描述可以概括为三个方面:</p>
<blockquote>
<p>准确的输入 </p>
<p>准确的输出 </p>
<p>准确的约束条件</p>
</blockquote>
<h3 id="算法,灵机一动"><a href="#算法,灵机一动" class="headerlink" title="算法,灵机一动"></a>算法,灵机一动</h3><p> 先进的算法有时候对软件系统影响很大——减少开发时间,同时使得执行效率更快。在算法中所谓的灵机一动,看似是“看起来很困难的问题也可以有一个简单的、意想不到的答案”。算法的灵机一动,并非只有大量的研究以后才能出现,需要的是编程之前、之中和之后进行认真的思考。伴随着这种思考,往往就能捕获到这灵机一动。</p>
<h3 id="数据决定数据结构"><a href="#数据决定数据结构" class="headerlink" title="数据决定数据结构"></a>数据决定数据结构</h3><p> 恰当的数据视图实际上决定了程序的结构。通过重新组织内部数据是程序变得更好。在我们工作中,很多时候是可以用小程序完成任务的情况下,程序员往往最终写出了又大又纯的程序。其主要原因就是惰性:不去尝试思考,而急于完成最初的想法。<br> 程序员在节省空间方面无计可施时,将自己从代码中解脱出来,退回起点并集中心机去研究数据,常常会有奇效。数据的表示形式是程序设计的根本。退回起点的原则:</p>
<ol>
<li>使用数组代替重复的代码</li>
<li>封装复杂结构</li>
<li>尽可能使用高级工具</li>
<li>从数据得出程序结构</li>
</ol>
<h3 id="编写正确的程序"><a href="#编写正确的程序" class="headerlink" title="编写正确的程序"></a>编写正确的程序</h3><p> 必须引起注意的是,编程技巧仅仅是编写正确程序的很小一部分,大部分内容还是:问题定义、算法设计和数据结构的选择。遵循这几点的话,编写正常的程序通常是很容易的。除此之外,要记得使用测试用例和断言等去验证程序的正确性。</p>
<h3 id="让编写的程序真正可用"><a href="#让编写的程序真正可用" class="headerlink" title="让编写的程序真正可用"></a>让编写的程序真正可用</h3><p> 程序员都是乐观主义者,他们总是认为讲编写完的程序,插入系统中就可以正常运行。在大部分时间是可行的,但是有的时候确实灾难性的存在,我们不得不需要在庞大的系统中,去寻找这个错误的小小的程序。<br> 良好的使用断言,可以知道程序的开发,同时也可以用来判断程序的正确性。这里作者提到了一个对于断言使用的一个小嘲讽:在测试时使用断言,而产品发布时将断言关闭的程序员,就好比在岸上操练时穿着救生衣,而下海时将救生衣脱下的水手。<br> 为了程序的可用性,往往自动测试和时间计数也显得至关重要。具有完整且完善边界测试用例能够保证程序的准确性,而且可以提高测试效率。同时,时间计数可以直观的观察程序的运行时间复杂度。</p>
<h3 id="来聊聊性能"><a href="#来聊聊性能" class="headerlink" title="来聊聊性能"></a>来聊聊性能</h3><p> 一个简单而又功能强大的程序,往往令用户欣喜而不令开发者烦恼,这是程序的终极目标。而其中一个重要的元素就是效率。低效率的程序往往令用户沮丧。等待的时间越长,也就意味着越高的概率会失去用户。而如何提高效率我们往往考虑以下途径:</p>
<ol>
<li>通过积累经验,选择恰当的方法</li>
<li>粗略估算运行时间</li>
<li>算法设计</li>
<li>代码调优</li>
</ol>
<h3 id="性能分析"><a href="#性能分析" class="headerlink" title="性能分析"></a>性能分析</h3><p> 而在真正进行效率优化的时候,从计算机系统的层面我们应该从以下方面进行:</p>
<ol>
<li>问题定义</li>
<li>系统结构:模块化;性能分析在系统设计阶段至关重要</li>
<li>算法和数据结构:快速的模块是基于其良好的表示的数据结构和操纵这些数据结构的算法</li>
<li>代码调优</li>
<li>系统软件</li>
<li>硬件</li>
</ol>
<h3 id="粗略评估"><a href="#粗略评估" class="headerlink" title="粗略评估"></a>粗略评估</h3><blockquote>
<p> 任何事都应尽量简单,但不易于过于简单 —— 爱因斯坦</p>
</blockquote>
<p> 我们知道简单的计算并不简单,因为我们为了补偿估算参数时的错误和对问题的了解不足,我们往往会选定和包含安全系数。</p>
<h3 id="算法设计技术"><a href="#算法设计技术" class="headerlink" title="算法设计技术"></a>算法设计技术</h3><p> 几个重要的算法设计技术</p>
<ol>
<li>保存状态,避免重复计算</li>
<li>将信息预处理至数据结构中</li>
<li>分治算法</li>
<li>扫描算法</li>
<li>累加算法</li>
<li>下界</li>
</ol>
<h3 id="代码调优"><a href="#代码调优" class="headerlink" title="代码调优"></a>代码调优</h3><p> 代码调优很重要的一点是把握调优的尺度。有些程序猿过于关注程序的效率,由于太在乎细小的“优化”,它们编写出的程序过于精妙,难以维护。而一些程序员很少关注程序的效率,它们编写的程序有着清晰漂亮的结构,但效率极低以至于毫无用处。往往获取更多的可用内存空间,需要在程序的性能、功能或者可维护性上做出牺牲,所以优化的前提永远是正确的决策。<br> 代码调优是一个在程序中需要做整体考虑的工作项目,但其根本目的是解决程序中开销过大的部分,对其进行少量修改,以提高运行效率。所谓开销包括CPU时间和程序存储空间。<br> 作者在文中给出了代码调优的原理:</p>
<blockquote>
<p>代码调优的最重要远离就是尽量少用它 </p>
<ol>
<li>效率的角色: 没有坏的话就不要修</li>
<li>设计层面: 只有确定没有更好的解决方案时,才考虑进行代码调优</li>
<li>双刃剑</li>
</ol>
</blockquote>
<h3 id="节省空间"><a href="#节省空间" class="headerlink" title="节省空间"></a>节省空间</h3><p> 努力的考虑一下空间紧凑的程序是很有意义的。在节省空间的同时,我们往往会得到运行时间上产生的副作用:程序小意味着加载更快,也更容易填入高速缓存中,操作的数据变少意味着操作时间变少等等。<br> 简单性可以衍生出功能性、健壮性以及速度和空间。<br> 这里列出一些较少程序所需数据的存储空间的技术:</p>
<ol>
<li>不存储、重新计算</li>
<li>稀疏数据结构</li>
<li>数据压缩</li>
<li>分配策略</li>
<li>垃圾回收</li>
</ol>
<h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><p> 将一些列记录排成有序的,最后也是最容易的办法就是使用排序函数库。但是并非总是有效的,这时我们别无选择,只能编写自己的排序函数。</p>
<h3 id="堆"><a href="#堆" class="headerlink" title="堆"></a>堆</h3><p> 采用堆排序不会超过O(nlogn),并且只需要几个额外的字节。</p>
<hr>
<h1 id="写到最后"><a href="#写到最后" class="headerlink" title="写到最后"></a>写到最后</h1><p> 读者用实践和经验去讲述程序中的问题,其实也是对我们工作和学习方法的一种提示。勿要死读书,读死书,要结合实际灵活运用。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[网站浏览记录]]></title>
<url>http://lennybai.cn/2016/12/05/%E7%BD%91%E7%AB%99%E6%B5%8F%E8%A7%88%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p> 我习惯每天花上一些时间,根据今天的疑问去搜索一些博客读一读。经常会看到一些让人为之振奋的讲解,但也因为读的多读的泛,让自己很难记起某些知识点的具体位置。这让自己想再次翻阅的时候很是焦灼。现在想想何不记录一番,方便以后查阅呢?</p>
<a id="more"></a>
<h3 id="大型网站架构"><a href="#大型网站架构" class="headerlink" title="大型网站架构"></a>大型网站架构</h3><ol>
<li><a href="http://www.cnblogs.com/elves/p/4259188.html" target="_blank" rel="external">大型网站改进历程</a></li>
<li><a href="http://www.cnblogs.com/itfly8/p/5006197.html" target="_blank" rel="external">大型网站架构案例</a></li>
</ol>
<h3 id="数据库缓存"><a href="#数据库缓存" class="headerlink" title="数据库缓存"></a>数据库缓存</h3><ol>
<li><a href="http://www.360sdn.com/architect/2015/0504/8691.html" target="_blank" rel="external">mysql+memcached</a></li>
<li><a href="http://www.voidcn.com/blog/bantiaomichong/article/p-6158870.html" target="_blank" rel="external">mysql+redis</a></li>
<li><a href="http://storage.ctocio.com.cn/394/12737894.shtml" target="_blank" rel="external">redis应用</a></li>
</ol>
<h3 id="编程珠玑"><a href="#编程珠玑" class="headerlink" title="编程珠玑"></a>编程珠玑</h3><ol>
<li><a href="http://www.hawstein.com/posts/make-thiner-programming-pearls.html" target="_blank" rel="external">把编程珠玑读薄</a></li>
<li><a href="http://mingyangshang.github.io/2016/01/01/%E7%BC%96%E7%A8%8B%E7%8F%A0%E7%8E%91/" target="_blank" rel="external">编程珠玑</a></li>
</ol>
<h3 id="elasticsearch"><a href="#elasticsearch" class="headerlink" title="elasticsearch"></a>elasticsearch</h3><ol>
<li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" target="_blank" rel="external">官方文档</a></li>
<li><a href="http://udn.yyuap.com/doc/mastering-elasticsearch/index.html" target="_blank" rel="external">mastering elasticsearch(中文版)</a></li>
</ol>
<h3 id="机器学习"><a href="#机器学习" class="headerlink" title="机器学习"></a>机器学习</h3><ol>
<li><a href="http://www.aboutyun.com/thread-19304-1-1.html" target="_blank" rel="external">用户在线广告点击行为预测的深度学习模型</a></li>
<li><a href="http://blog.csdn.net/han_xiaoyang/article/details/50469334" target="_blank" rel="external">机器学习算法</a></li>
<li><a href="https://www.zhihu.com/question/26726794" target="_blank" rel="external">机器学习算法及其应用场景</a></li>
<li><a href="http://download.csdn.net/detail/jkhere/6438773" target="_blank" rel="external">机器学习十大算法</a></li>
</ol>
<h3 id="CAS-SSO"><a href="#CAS-SSO" class="headerlink" title="CAS SSO"></a>CAS SSO</h3><ol>
<li><a href="http://blog.csdn.net/zhurhyme/article/category/2362091/3" target="_blank" rel="external">cas入门</a></li>
</ol>
]]></content>
</entry>
<entry>
<title><![CDATA[effective c++小记]]></title>
<url>http://lennybai.cn/2016/12/02/effective-c-%E5%B0%8F%E8%AE%B0/</url>
<content type="html"><![CDATA[<p>more effective c++</p>
]]></content>
</entry>
<entry>
<title><![CDATA[算法导论(1)——写好伪代码]]></title>
<url>http://lennybai.cn/2016/12/02/%E7%AE%97%E6%B3%95%E5%AF%BC%E8%AE%BA1/</url>
<content type="html"><![CDATA[<p> 在学习各种编程语言的时候,数据结构与算法一般都会作为重点课程来指出。而谈到算法,算法导论一书又常常被大家提起。然而作为一个编程界的老鸟,技术层面的菜鸟,最近才开始啃算法导论,实属令自己汗颜。不过拾起总比放下的要好,所以这里根据自己的理解做一些记录。并在阅读初期就设定了一些目标,包括理解并学习各种常用算法及其设计思路,<strong><em>学习并写好伪代码</em></strong>等。</p>
<a id="more"></a>
<h3 id="什么是算法"><a href="#什么是算法" class="headerlink" title="什么是算法"></a>什么是算法</h3><p> 书中讲到,算法就是任何良定义的计算过程。算法的目的是解决问题。问题陈述说明了期望的输入和输出,而算法则描述一个特定的计算过程来实现输入输出的关系。</p>
<h3 id="算法的描述(伪代码)"><a href="#算法的描述(伪代码)" class="headerlink" title="算法的描述(伪代码)"></a>算法的描述(伪代码)</h3><p> 算法可以使用英语说明,也可以用中文说明,当然也可以说明成计算机程序。它的唯一要求是这个说明必须精确的描述所需要遵循的计算过程。<br> 我个人更欣赏将算法描述为用一种伪代码书写的程序。它的优势在于,能够使用最清晰最简洁的方法来说明给定的算法。并且根据伪代码可以将算法转化成各种所需的编程语言。</p>
<h3 id="如何写好伪代码"><a href="#如何写好伪代码" class="headerlink" title="如何写好伪代码"></a>如何写好伪代码</h3><p> 在我们常用的编程语言中,通常按照所需的命名规范和运算逻辑的使用,讲所想的用该语言展示出来。伪代码同样也可以按照相似的方法展示。其实伪代码并没有明确的规范要求,但是在算法导论一书中,他列出了一些所谓的约定。当然,这些约定我们可以不去遵守。但是如果按着约定去书写伪代码的话,会使我们的伪代码变得清晰易懂,何乐不为。</p>
<ul>
<li>缩进表示块结构。参考python的语言结构。 </li>
<li>while,for,if-else等结构具有和c语言等相同的解释。但是方便理解,我们去除额外的细节,表示重点。比如当一个for循环时,当循环上升时使用to,下降时使用downto,步数使用by。</li>
<li>//表示注释</li>
<li>变量直接使用无需声明。一般变量默认为局部变量。</li>
<li>数据访问通过数组名和下标的方式访问。</li>
<li>使用error表示过程中出现错误。</li>
</ul>
<p> 伪代码的使用方法和约定都比较宽松,目的都是能够写出清晰易懂的伪代码。</p>
<h3 id="伪代码实践"><a href="#伪代码实践" class="headerlink" title="伪代码实践"></a>伪代码实践</h3><p> 这里列举一个插入排序的算法的伪代码实现,大家一起来感受一下气场。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">INSERT-SORT(A)</div><div class="line"> for j=2 to A.length</div><div class="line"> key=A[j]</div><div class="line"> // Insert A[j] into the sorted sequence A[1..j-1].</div><div class="line"> i = j-1;</div><div class="line"> while i>0 and A[i]>key</div><div class="line"> A[i+1]=A[j]</div><div class="line"> i = i-1</div><div class="line"> A[i+1]=key</div></pre></td></tr></table></figure></p>
<h3 id="归并排序-merge-sort"><a href="#归并排序-merge-sort" class="headerlink" title="归并排序(merge sort)"></a>归并排序(merge sort)</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line">MERGE(A,p,q,r)</div><div class="line"> n1=q-p+1</div><div class="line"> n2=r-q</div><div class="line"> let L[0..n1] and R[0..n2] be a new array</div><div class="line"> for i = 0 to n1-1</div><div class="line"> L[i]=A[p+i]</div><div class="line"> for j = 0 to n2-1</div><div class="line"> R[j]=A[q+1+j]</div><div class="line"> L[n1]=∞</div><div class="line"> L[n2]=∞</div><div class="line"> i=0</div><div class="line"> j=0</div><div class="line"> for k = p to r</div><div class="line"> if L[i] < R[j]</div><div class="line"> A[k]=L[i]</div><div class="line"> i = i + 1</div><div class="line"> else</div><div class="line"> A[k]=R[j]</div><div class="line"> j = j +1</div><div class="line"></div><div class="line">MERGE-SORT(A,p,r)</div><div class="line"> if(p<r)</div><div class="line"> q=[(p+r)/2]</div><div class="line"> MERGE-SORT(A,p,q)</div><div class="line"> MERGE-SORT(A,q+1,r)</div><div class="line"> MERGE(A,p,q,r)</div></pre></td></tr></table></figure>
]]></content>
</entry>
<entry>
<title><![CDATA[elasticsearch上手练]]></title>
<url>http://lennybai.cn/2016/12/02/elasticsearch%E4%B8%8A%E6%89%8B%E7%BB%83/</url>
<content type="html"><![CDATA[<h1 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h1><p> elasticsearch现在在企业应用中很是火爆。快速日志检索,简单高校的分布式支持等等都是它的优势所在。ELK的组合使用也是经典的使用场景。<br><a id="more"></a></p>
<h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><p> elasticsearch的官方文档非常清晰,不论是对其原理的介绍,还有api的讲解。希望大家还是耐心阅读一番。除此之外,这里还有一个我看到的中文版本的连接,有作者的自己思考,也很不错。</p>
<ol>
<li><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" target="_blank" rel="external">elasticsearch官方文档</a></li>
<li><a href="http://udn.yyuap.com/doc/mastering-elasticsearch/index.html" target="_blank" rel="external">Mastering Elasticsearch(中文版)</a></li>
</ol>
<h1 id="我的实践"><a href="#我的实践" class="headerlink" title="我的实践"></a>我的实践</h1><p> <a href="https://github.com/geeklenny/elasticsearch-restful-javaee-spring-django-rabitmq" target="_blank" rel="external">实践代码</a><br> 这里我提供了一个简单的elasticsearch的实现。主要是通过spring实现了一套restful的后台接口。后台使用elasticsearch进行持久化。同时,使用django提供了一套前端系统。实现比较粗糙,跪在理解和使用练习。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[数据库线程池(c++)]]></title>
<url>http://lennybai.cn/2016/12/02/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E6%B1%A0(c++)/</url>
<content type="html"><![CDATA[<h1 id="一、概述"><a href="#一、概述" class="headerlink" title="一、概述"></a>一、概述</h1><p> 对于每一次的数据库访问,都需要有一个承载该次访问操作的数据库连接。现在的应用系统往往伴随着大量的数据库访问。可想而知,如果频繁的建立和关闭链接,会极大的降低系统的性能。</p>
<p> 数据库连接池是针对数据库连接的性能优化而产生的。它的核心思想是连接复用,并通过连接池高效并安全的维护连接池内的连接,并按需分配到各个调用者,以减少重复创建和删除连接造成的系统资源浪费。</p>
<a id="more"></a>
<h2 id="1-1-源代码链接"><a href="#1-1-源代码链接" class="headerlink" title="1.1 源代码链接"></a>1.1 源代码链接</h2><p><a href="https://github.com/geeklenny/databaseConnPool" target="_blank" rel="external">数据库连接池</a></p>
<h1 id="二、源代码讲解"><a href="#二、源代码讲解" class="headerlink" title="二、源代码讲解"></a>二、源代码讲解</h1><p> 希望你已经下载了源代码,这里开始对源代码进行讲解。这一份源代码我并没有做过多的性能测试,只是按照数据库连接池的基本思想和原理提供的一份实现。我希望这篇文章可以覆盖到数据库连接池的核心内容。</p>
<h2 id="2-1-连接池只是连接池"><a href="#2-1-连接池只是连接池" class="headerlink" title="2.1 连接池只是连接池"></a>2.1 连接池只是连接池</h2><p> 我们编写连接池的目的是用来维护连接,减少系统资源浪费。所以我们避免将连接池设计和实现成通用的带数据库连接优化的数据库访问类。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">class</span> CommonDbConnPool{...}</div></pre></td></tr></table></figure>
<p> 我们使用模板类来弱化数据库的具体类型,而更关系如何去维护其链接。对于具体的数据库操作,还是沿用使用的数据库提供的接口去访问。记住,数据库连接池只提供可用的连接,或者无可用连接时的错误提示。</p>
<h2 id="2-2-连接的初始化"><a href="#2-2-连接的初始化" class="headerlink" title="2.2 连接的初始化"></a>2.2 连接的初始化</h2><p> 提高数据库链接的初始化,核心的问题是启动多少连接合适。启动太少,不能满足应用的需求;启动太多,对系统资源也是一种浪费。实际上,在什么样配置的服务器上,启动多少个连接合适并没有一个明确的参考数据。它们都需要进行测试,调整到最优的连接数。<br> 这里提供一个普遍适用于连接池的方法。它可以尽可能的保证系统资源的合理使用。这个方法是通常提供一个最小连接数和最大连接数。最小连接数为启动时默认启动的链接数目。如果最小连接数在被完全使用的时候,又进入一个新连接,那么连接池将为它新建一个连接。新建连接的前提是,连接总数没有超过最大连接数。否则返回连接池已满类似的错误信息。超出最小连接数的这些连接,会被定期回收释放。<br> 初始化的同时,启动监控线程,用于定期检测连接是否正常连接。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">int</span> CommonDbConnPool<T>::InitPool( <span class="keyword">int</span> minConn, <span class="keyword">int</span> maxConn )</div><div class="line">{</div><div class="line"> ...</div><div class="line"> ...</div><div class="line"> <span class="keyword">for</span> ( <span class="keyword">int</span> i =<span class="number">0</span> ; i < minConn; i++ )</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( (t = createDBConn()) != <span class="literal">nullptr</span> )</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( (bConnectionAvilable(t)) )</div><div class="line"> {</div><div class="line"> m_poolMap[t] = DB_CONN_FREE;</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span></div><div class="line"> {</div><div class="line"> releaseDBConn(t);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> ...</div><div class="line"> ...</div><div class="line"> <span class="function">thread <span class="title">th</span><span class="params">(&CommonDbConnPool<T>::PoolConnMonitor, <span class="keyword">this</span>)</span></span>;</div><div class="line"> swap(th, m_trdConnMonitor);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="2-3-连接的管理"><a href="#2-3-连接的管理" class="headerlink" title="2.3 连接的管理"></a>2.3 连接的管理</h2><p> 存在与连接池中的连接有三种状态。空闲,占用和临时连接。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">enum</span> DBCONNSTATS</div><div class="line">{</div><div class="line"> DB_CONN_FREE,</div><div class="line"> DB_CONN_USED,</div><div class="line"> DB_CONN_TEMP_USED</div><div class="line"></div><div class="line">};</div></pre></td></tr></table></figure></p>
<p> 最小连接数内的连接,初始化为free,占用时为used。而超过最小链接,并未超过最大连接数的这些连接为临时连接,定期会被回收。当然什么时候回收由你来定,我的是现实,当连接被用户释放回连接池时,直接回收。很多的数据库连接池对于临时连接处理会巧妙的多。比如超过最小链接后,扩容一倍等等。<br> <strong>需要强调的一点是,为了保证多线程的安全访问,请记得加锁。</strong></p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></div><div class="line">T* CommonDbConnPool<T>::GetDBConnFromPool()</div><div class="line">{</div><div class="line"> ...</div><div class="line"> lock_guard<mutex> locker(m_mtxPool);</div><div class="line"> ...</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span> &iter : m_poolMap)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>(iter.second == DB_CONN_FREE){</div><div class="line"> iter.second = DB_CONN_USED;</div><div class="line"> t = iter.first;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (t == <span class="literal">nullptr</span>){</div><div class="line"> <span class="keyword">if</span>(m_poolMap.size() < m_maxConn)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( (t = createDBConn()) != <span class="literal">nullptr</span> )</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( (bConnectionAvilable(t)) )</div><div class="line"> {</div><div class="line"> m_poolMap[t] = DB_CONN_TEMP_USED;</div><div class="line"> }</div><div class="line"> <span class="keyword">else</span></div><div class="line"> {</div><div class="line"> releaseDBConn(t);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> t;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">void</span> CommonDbConnPool<T>::ReleaseDbConnToPool(T* t)</div><div class="line">{</div><div class="line"> lock_guard<mutex> locker(m_mtxPool);</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> &iter : m_poolMap)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>(iter.first == t)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>(iter.second == DB_CONN_USED)</div><div class="line"> {</div><div class="line"> iter.second = DB_CONN_FREE;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (iter.second == DB_CONN_TEMP_USED)</div><div class="line"> {</div><div class="line"> releaseDBConn(iter.first);</div><div class="line"> m_poolMap.erase(iter.first);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="2-4-释放连接池"><a href="#2-4-释放连接池" class="headerlink" title="2.4 释放连接池"></a>2.4 释放连接池</h2><p> 释放连接也应该人性化,比如某个应用还在使用连接进行着访问,那我们不应该直接关闭该链接。<br> 我这里的处理是,关闭所有free的链接。并返回池内连接的大小。如果返回不为0,那么就相当于通知用户,连接并没有完全被释放,你还需要再次调用。<br> 别忘了我们还有一个监控线程在运行着呢。别忘了结束线程。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">void</span> CommonDbConnPool<T>::PoolConnMonitor(){</div><div class="line"> ...</div><div class="line"> <span class="keyword">while</span>(ptrPool->m_bPoolAvailable && ! ptrPool->m_bPoolToDestroy)</div><div class="line"> {</div><div class="line"> ...</div><div class="line"> [&](){</div><div class="line"> unique_lock<mutex> lk(ptrPool->m_mtxCv);</div><div class="line"> ptrPool->m_Cv.wait_for(lk, chrono::milliseconds(ptrPool->ulTimeForCheckTimeout()));</div><div class="line"> }();</div><div class="line"> ...</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> T></div><div class="line"><span class="keyword">int</span> CommonDbConnPool<T>::DestroyPool(){</div><div class="line"> ...</div><div class="line"> <span class="keyword">for</span>( <span class="keyword">auto</span> &iter : m_poolMap)</div><div class="line"> {</div><div class="line"> <span class="keyword">if</span>( iter.second == DB_CONN_FREE)</div><div class="line"> {</div><div class="line"> releaseDBConn(iter.first);</div><div class="line"> m_poolMap.erase(iter.first);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> ...</div><div class="line"> ...</div><div class="line"> ptrPool->m_bPoolToDestroy = <span class="literal">true</span>;</div><div class="line"> m_Cv.notify_one();</div><div class="line"> m_trdConnMonitor.join();</div><div class="line"></div><div class="line"> ...</div><div class="line"> <span class="keyword">return</span> m_poolMap.size();</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h1 id="三、使用"><a href="#三、使用" class="headerlink" title="三、使用"></a>三、使用</h1><p> 我这里使用了mysqlcppconn的库,如果需要请自行安装下载。<br> <figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"./mysql/mysqlConn.h"</span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"></div><div class="line"> MysqlConn* mysqlpool;</div><div class="line"> <span class="keyword">try</span>{</div><div class="line"></div><div class="line"> <span class="keyword">do</span>{</div><div class="line"></div><div class="line"> <span class="comment">//连接数据库</span></div><div class="line"> mysqlpool = <span class="keyword">new</span> MysqlConn(<span class="string">"localhost"</span>, <span class="string">"root"</span>, <span class="string">"Passw0rd"</span>);</div><div class="line"></div><div class="line"> <span class="comment">//创建数据库连接池,并返回大小</span></div><div class="line"> <span class="built_in">cout</span> << <span class="string">" mysqlpool size : "</span> << mysqlpool->InitPool(<span class="number">10</span>,<span class="number">20</span>) << <span class="built_in">endl</span>;</div><div class="line"></div><div class="line"> sql::Connection *con;</div><div class="line"> sql::Statement* stmt;</div><div class="line"> sql::ResultSet* res;</div><div class="line"></div><div class="line"> <span class="comment">//获取一个连接</span></div><div class="line"> <span class="keyword">if</span>((con=mysqlpool->GetDBConnFromPool())==<span class="literal">nullptr</span>){</div><div class="line"> <span class="built_in">cout</span><<<span class="string">"reach the max availd"</span> << <span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">//执行语句</span></div><div class="line"> con->setSchema(<span class="string">"mysql"</span>);</div><div class="line"> stmt = con->createStatement();</div><div class="line"> res = stmt->executeQuery(<span class="string">"select * from user"</span>);</div><div class="line"></div><div class="line"> <span class="comment">//打印数据库连接池信息</span></div><div class="line"> <span class="built_in">cout</span><<(*mysqlpool);</div><div class="line"></div><div class="line"> <span class="comment">//释放连接到连接池</span></div><div class="line"> mysqlpool->ReleaseDbConnToPool(con);</div><div class="line"></div><div class="line"> <span class="comment">//打印数据库连接池信息</span></div><div class="line"> <span class="built_in">cout</span><<(*mysqlpool);</div><div class="line"> <span class="built_in">cin</span>.get();</div><div class="line"></div><div class="line"> } <span class="keyword">while</span>(<span class="literal">false</span>);</div><div class="line"> <span class="comment">//销毁数据库连接池</span></div><div class="line"> <span class="keyword">if</span>(mysqlpool->DestroyPool()><span class="number">0</span>){</div><div class="line"> <span class="built_in">cout</span><<<span class="string">"There are still some un-release connections in the pool\n"</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">delete</span> mysqlpool;</div><div class="line"></div><div class="line"> }<span class="keyword">catch</span>(sql::SQLException &e){</div><div class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span><<e.what();</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
</entry>
<entry>
<title><![CDATA[redis学习之参考文档]]></title>
<url>http://lennybai.cn/2016/12/02/redis%E5%AD%A6%E4%B9%A0%E4%B9%8B%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3/</url>
<content type="html"><![CDATA[<h1 id="1-认识redis"><a href="#1-认识redis" class="headerlink" title="1. 认识redis"></a>1. 认识redis</h1><p> redis是一个key-value的存储系统。它支持网络、可基于内存亦可持久化的日志型、key-value数据库。value值可支持string,map,list,sets和sorted sets等类型。<br> 详细的说,redis相对其它key-value缓存产品(如memcached)有三个特点:</p>
<ul>
<li>支持持久化,可将内存中的数据保持到磁盘中,重启时可再次加载进行使用。</li>
<li>不仅仅支持简单的key-value类型的数据,同事还提供list,set,zset,hash等数据结构的存储</li>
<li>支持数据备份,master-slave模式</li>
</ul>
<a id="more"></a>
<p> 除此之外,redis还具备一下特点:</p>
<ul>
<li>极高的性能: 读110000次/s, 写的速度81000次/s</li>
<li>丰富的数据类型</li>
<li>原子性:所有操作都是原子性的。</li>
<li>丰富的特性: 支持通知、key过期,publish/subscribe等</li>
</ul>
<h1 id="2-使用redis"><a href="#2-使用redis" class="headerlink" title="2.使用redis"></a>2.使用redis</h1><p> 对于一个工具,我们更关心的是如何使用。这里我从官方的文档中摘录出一些我自己比较感性去的部分罗列与此。和大家分享。</p>
<h2 id="2-1-配置Redis"><a href="#2-1-配置Redis" class="headerlink" title="2.1 配置Redis"></a>2.1 配置Redis</h2><p> 如何正确的使用配置文件,有利于我们更好的使用redis。这里我们认识一下常用命令。我安装了redis-cli,这里直接使用。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">lennybai@lennybai:~$ redis-cli</div><div class="line">127.0.0.1:6379> CONFIG GET loglevel</div><div class="line">1) <span class="string">"loglevel"</span></div><div class="line">2) <span class="string">"notice"</span></div><div class="line">127.0.0.1:6379> config get *</div><div class="line"> 1) <span class="string">"dbfilename"</span></div><div class="line"> 2) <span class="string">"dump.rdb"</span></div><div class="line"> 3) <span class="string">"requirepass"</span></div><div class="line"> 4) <span class="string">""</span></div><div class="line"> 5) <span class="string">"masterauth"</span></div><div class="line"> 6) <span class="string">""</span></div><div class="line"> 7) <span class="string">"unixsocket"</span></div><div class="line"> 8) <span class="string">""</span></div><div class="line"> 9) <span class="string">"logfile"</span></div><div class="line"> 10) <span class="string">"/var/log/redis/redis-server.log"</span></div><div class="line"> 11) <span class="string">"pidfile"</span></div><div class="line">..........后面省略</div></pre></td></tr></table></figure></p>
<p> 我们可以通过config get key获取配置文件中某项配置的值。并可以通过config set config_string_name new_config_value来更新其值。<br> 下面对一些常用的配置项进行说明:</p>
<table>
<thead>
<tr>
<th>命令</th>
<th> 说明 </th>
</tr>
</thead>
<tbody>
<tr>
<td>daemonize</td>
<td>是否设为守护进程</td>
</tr>
<tr>
<td>pidfile</td>
<td>设置守护进程pid存储文件的位置</td>
</tr>
<tr>
<td>port</td>
<td>指定redis端口(默认6379)</td>
</tr>
<tr>
<td>databases</td>
<td>设置redis内置数据库的数量。通过select切换</td>
</tr>
<tr>
<td>save</td>
<td>指定同步到文件的规则</td>
</tr>
<tr>
<td>maxclient</td>
<td>最大客户连接数,0为不设限制</td>
</tr>
<tr>
<td>maxmemory</td>
<td>最大分配内存</td>
</tr>
</tbody>
</table>
<p>对于命令还有很多,大家可以在需要时自行查看。</p>
<h2 id="2-2-redis数据类型"><a href="#2-2-redis数据类型" class="headerlink" title="2.2 redis数据类型"></a>2.2 redis数据类型</h2><p> 数据类型对于redis相对其他缓存产品而言,其丰富的数据格式是它的一大特色。这里做一下简单的介绍。</p>
<h3 id="string字符串类型"><a href="#string字符串类型" class="headerlink" title="string字符串类型"></a>string字符串类型</h3><p> string类型是最基本的类型,它和memcached一样的类型.一个key对应一个value。redis中,string是二进制安全的,也就是说它可以存储任何数据(如图片或者序列化的对象)。一个键的最大存储为512MB.<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> SET name <span class="string">"redis.net.cn"</span></div><div class="line">OK</div><div class="line">redis 127.0.0.1:6379> GET name</div><div class="line"><span class="string">"redis.net.cn"</span></div></pre></td></tr></table></figure></p>
<h3 id="hash(哈希"><a href="#hash(哈希" class="headerlink" title="hash(哈希)"></a>hash(哈希)</h3><p>Redis hash是一个键值组合,它是一个string类型的field和value的映射表。特别适合存储对象。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> HMSET user:1 username redis.net.cn password redis.net.cn points 200</div><div class="line">OK</div><div class="line">redis 127.0.0.1:6379> HGETALL user:1</div><div class="line">1) <span class="string">"username"</span></div><div class="line">2) <span class="string">"redis.net.cn"</span></div><div class="line">3) <span class="string">"password"</span></div><div class="line">4) <span class="string">"redis.net.cn"</span></div><div class="line">5) <span class="string">"points"</span></div><div class="line">6) <span class="string">"200"</span></div></pre></td></tr></table></figure></p>
<p>每个 hash 可以存储 232 - 1 键值对(40多亿)。</p>
<h3 id="list-列表"><a href="#list-列表" class="headerlink" title="list(列表)"></a>list(列表)</h3><p> redis list列表是简单的string类型列表。可以添加一个元素在列表的头部或者尾部。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> lpush redis.net.cn redis</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> lpush redis.net.cn mongodb</div><div class="line">(<span class="built_in">integer</span>) 2</div><div class="line">redis 127.0.0.1:6379> lpush redis.net.cn rabitmq</div><div class="line">(<span class="built_in">integer</span>) 3</div><div class="line">redis 127.0.0.1:6379> lrange redis.net.cn 0 10</div><div class="line">1) <span class="string">"rabitmq"</span></div><div class="line">2) <span class="string">"mongodb"</span></div><div class="line">3) <span class="string">"redis"</span></div><div class="line">redis 127.0.0.1:6379></div></pre></td></tr></table></figure></p>
<p>列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。</p>
<h3 id="set-集合"><a href="#set-集合" class="headerlink" title="set(集合)"></a>set(集合)</h3><p> Redis的set是string类型的无序集合。它是通过hash表实现的。增添和查找的复杂度为O(1).</p>
<blockquote>
<p>sadd key member</p>
</blockquote>
<p>实例</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> sadd redis.net.cn redis</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> sadd redis.net.cn mongodb</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> sadd redis.net.cn rabitmq</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> sadd redis.net.cn rabitmq</div><div class="line">(<span class="built_in">integer</span>) 0</div><div class="line">redis 127.0.0.1:6379> smembers redis.net.cn</div><div class="line"></div><div class="line">1) <span class="string">"rabitmq"</span></div><div class="line">2) <span class="string">"mongodb"</span></div><div class="line">3) <span class="string">"redis"</span></div></pre></td></tr></table></figure>
<h3 id="zset(有序集合"><a href="#zset(有序集合" class="headerlink" title="zset(有序集合)"></a>zset(有序集合)</h3><p> zset是一个有序的string集合,且不允许成员重复。每个成员会关联一个double类型的分数。通过分数进行排序。成员唯一,但是分数可以重复。</p>
<blockquote>
<p>zadd key score member</p>
</blockquote>
<p>实例</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> zadd redis.net.cn 0 redis</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> zadd redis.net.cn 0 mongodb</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq</div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line">redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq</div><div class="line">(<span class="built_in">integer</span>) 0</div><div class="line">redis 127.0.0.1:6379> ZRANGEBYSCORE redis.net.cn 0 1000</div><div class="line"></div><div class="line">1) <span class="string">"redis"</span></div><div class="line">2) <span class="string">"mongodb"</span></div><div class="line">3) <span class="string">"rabitmq"</span></div></pre></td></tr></table></figure>
<h2 id="2-3-Redis命令"><a href="#2-3-Redis命令" class="headerlink" title="2.3 Redis命令"></a>2.3 Redis命令</h2><p> 通过介绍redis的命令,了解redis的使用</p>
<h3 id="PING"><a href="#PING" class="headerlink" title="PING"></a>PING</h3><p> redis可以通过ping命令检测redis的运行情况。若正常运行,则返回pung<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> PING</div><div class="line"></div><div class="line">PONG</div></pre></td></tr></table></figure></p>
<h3 id="key相关命令"><a href="#key相关命令" class="headerlink" title="key相关命令"></a>key相关命令</h3><table>
<thead>
<tr>
<th>命令 </th>
<th> 说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Set key</td>
<td>插入一个key-value</td>
</tr>
<tr>
<td>del key</td>
<td>删除一个key-value.正确返回1,错误返回0</td>
</tr>
<tr>
<td>dump key</td>
<td>序列化key。正确返回序列化后字符串,错误返回nil</td>
</tr>
</tbody>
</table>
<p>exists key | 检测键值是否存在<br>expire key seconds | 设置键值过期时间,时间到了自动删除<br>move key db | 将当前数据库的key移动到其他数据库<br>persist key | 移除过期时间,永久保存<br>rename key new key | 重命名key<br>type key | 返回key的类型</p>
<h3 id="publish-subscribe命令"><a href="#publish-subscribe命令" class="headerlink" title="publish\subscribe命令"></a>publish\subscribe命令</h3><p> pub\sub是一个消息通信模式。通过subscribe订阅消息,然后通过publish发送消息。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#订阅者</span></div><div class="line">redis 127.0.0.1:6379> SUBSCRIBE redisChat</div><div class="line"></div><div class="line">Reading messages... (press Ctrl-C to quit)</div><div class="line">1) <span class="string">"subscribe"</span></div><div class="line">2) <span class="string">"redisChat"</span></div><div class="line">3) (<span class="built_in">integer</span>) 1</div></pre></td></tr></table></figure></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#发送者</span></div><div class="line">redis 127.0.0.1:6379> PUBLISH redisChat <span class="string">"Redis is a great caching technique"</span></div><div class="line"></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> PUBLISH redisChat <span class="string">"Learn redis by w3cschool.cc"</span></div><div class="line"></div><div class="line">(<span class="built_in">integer</span>) 1</div><div class="line"></div><div class="line"><span class="comment"># 订阅者的客户端会显示如下消息</span></div><div class="line">1) <span class="string">"message"</span></div><div class="line">2) <span class="string">"redisChat"</span></div><div class="line">3) <span class="string">"Redis is a great caching technique"</span></div><div class="line">1) <span class="string">"message"</span></div><div class="line">2) <span class="string">"redisChat"</span></div><div class="line">3) <span class="string">"Learn redis by w3cschool.cc"</span></div></pre></td></tr></table></figure>
<p> 通过unsubscribe退订频道。</p>
<h3 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h3><p> Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:</p>
<ul>
<li>事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。</li>
<li>事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。</li>
</ul>
<p>一个事务从开始到执行会经历以下三个阶段:</p>
<ul>
<li>开始事务。</li>
<li>命令入队。</li>
<li>执行事务。</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">redis 127.0.0.1:6379> MULTI</div><div class="line">OK</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> SET book-name <span class="string">"Mastering C++ in 21 days"</span></div><div class="line">QUEUED</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> GET book-name</div><div class="line">QUEUED</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> SADD tag <span class="string">"C++"</span> <span class="string">"Programming"</span> <span class="string">"Mastering Series"</span></div><div class="line">QUEUED</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> SMEMBERS tag</div><div class="line">QUEUED</div><div class="line"></div><div class="line">redis 127.0.0.1:6379> EXEC</div><div class="line">1) OK</div><div class="line">2) <span class="string">"Mastering C++ in 21 days"</span></div><div class="line">3) (<span class="built_in">integer</span>) 3</div><div class="line">4) 1) <span class="string">"Mastering Series"</span></div><div class="line"> 2) <span class="string">"C++"</span></div><div class="line"> 3) <span class="string">"Programming"</span></div></pre></td></tr></table></figure>
<p> discard取消事务执行。</p>
<h3 id="INFO"><a href="#INFO" class="headerlink" title="INFO "></a>INFO </h3><p>查看当前redis所有信息</p>
<h3 id="脚本支持"><a href="#脚本支持" class="headerlink" title="脚本支持"></a>脚本支持</h3><p> redis内置lua解析器</p>
<h2 id="2-4-Redis为什么不能取代关系型数据库"><a href="#2-4-Redis为什么不能取代关系型数据库" class="headerlink" title="2.4 Redis为什么不能取代关系型数据库"></a>2.4 Redis为什么不能取代关系型数据库</h2><ol>
<li>复杂的数据结构不好维护</li>
<li>存储于内存虽然访问速度较快,但是关系体现不出来。</li>
<li>存储成本高</li>
</ol>
<h1 id="3-参考文献"><a href="#3-参考文献" class="headerlink" title="3 参考文献"></a>3 参考文献</h1><ul>
<li>[1]: <a href="http://www.redis.net.cn/tutorial/3501.html" target="_blank" rel="external">redis官方文档</a></li>
<li>[2]: <a href="https://www.teakki.com/p/57dbd374d7d770e81877c75a" target="_blank" rel="external">redis为什么不能取代关系数据库</a></li>
</ul>
]]></content>
</entry>
<entry>
<title><![CDATA[g++ template class]]></title>
<url>http://lennybai.cn/2016/11/25/g-template-class/</url>
<content type="html"><![CDATA[<p>g++模板类,定义不能与声明分离。其原因是,模板类的实现不是在编译时,直接对cpp文件进行编译,而是在函数或者模板类在定义时,根据类型实现特定的源文件代码。其实,如果强行讲实现与声明分离也有方法,比如在头文件a.h中引用a.cpp,这样就可以做到定义与实现分离。但是这导致每次使用模板都会对源文件进行编译,造成编译时浪费。</p>
]]></content>
</entry>
<entry>
<title><![CDATA[linux 小技巧]]></title>
<url>http://lennybai.cn/2016/11/22/linux-%E5%B0%8F%E6%8A%80%E5%B7%A7/</url>
<content type="html"><![CDATA[<p>## 命令行对错误信息的处理<br> 在使用控制台的时候,往往在得到正确结果的同时,也会跟随者一些并不重要的错误信息,比如:</p>
<p><img src="http://ogelzbmrh.bkt.clouddn.com/findmysql.png" alt="find mysql"></p>
<p> 我们发现,当我们使用find命令去搜索mysql相关的内容的时候,除了我们想要的路径信息外,还有很多不必要的”permission denied”错误信息。这时候我们就可以通过将错误重定向到/dev/null来解决这个问题:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">find / -name mysql 2>/dev/null</div></pre></td></tr></table></figure></p>
<h2 id="64bit下编译32bit程序"><a href="#64bit下编译32bit程序" class="headerlink" title="64bit下编译32bit程序"></a>64bit下编译32bit程序</h2><pre><code>遇到问题就要尝试解决。关注这一点,是我打算在我的开发环境ubuntu64下编译和调试wine时遇到的。通过搜索资料和实践,发现chroot可以有效的解决这个问题。
</code></pre><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install dchroot debootstrap</div></pre></td></tr></table></figure>
<pre><code>更多内容请自行查阅
</code></pre>]]></content>
</entry>
<entry>
<title><![CDATA[了解c++11]]></title>
<url>http://lennybai.cn/2016/11/14/%E4%BA%86%E8%A7%A3c-11/</url>
<content type="html"><![CDATA[<h1 id="一、简介"><a href="#一、简介" class="headerlink" title="一、简介"></a>一、简介</h1><p> 起草本文的目的主要有两点:第一点,在c++11学习的过程中做一些摘要总结,尽量取其精华,为自己梳理出来一个比较清晰的记忆脉络;第二点,不得不说的就是随着年纪的增长,记忆力也开始变得并不那么可靠,做些记录,定期回头看看总是好的。<br> 文章会对c++11(其实是c++1x更准确些)的背景进行简要的概述,并尽量详细且准确的阐述c++11的新的特性。共同学习,不断进步。</p>
<h2 id="1-1-c-11概述"><a href="#1-1-c-11概述" class="headerlink" title="1.1 c++11概述"></a>1.1 c++11概述</h2><p> 我们生活中常常谈论的c++更多的是指传统c++,又或是可以称为c++98的版本。c++11也并不是什么神秘的新语言,而是基于传统c++发布13年后的第一次重大修订。它主要基于现在软件行业发展的新需求与新诉求进行的一种调整——增加新特性并弃用部分特性。</p>
<a id="more"></a>
<h2 id="1-2-文章小贴士"><a href="#1-2-文章小贴士" class="headerlink" title="1.2 文章小贴士"></a>1.2 文章小贴士</h2><h3 id="1-2-1-笔者开发运行环境"><a href="#1-2-1-笔者开发运行环境" class="headerlink" title="1.2.1 笔者开发运行环境"></a>1.2.1 笔者开发运行环境</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">> lennybai@lennybai~$ lsb_release <span class="_">-a</span></div><div class="line">> No LSB modules are available.</div><div class="line">> Distributor ID: Ubuntu</div><div class="line">> Description: Ubuntu 16.04.1 LTS</div><div class="line">> Release: 16.04</div><div class="line">> Codename: xenial</div><div class="line"></div><div class="line">> lennybai@lennybai:~$ g++ --version</div><div class="line">> g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609</div><div class="line">> Copyright (C) 2015 Free Software Foundation, Inc.</div><div class="line">> This is free software; see the <span class="built_in">source</span> <span class="keyword">for</span> copying conditions. There is NO</div><div class="line">warranty; not even <span class="keyword">for</span> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</div></pre></td></tr></table></figure>
<h3 id="1-2-2-小贴士"><a href="#1-2-2-小贴士" class="headerlink" title="1.2.2 小贴士"></a>1.2.2 小贴士</h3><blockquote>
<p>g++ main.cpp -std=c++11 </p>
</blockquote>
<p>若使用c++11,请记得添加编译选项</p>
<h3 id="1-2-3-原创提醒"><a href="#1-2-3-原创提醒" class="headerlink" title="1.2.3 原创提醒"></a>1.2.3 原创提醒</h3><p> 本文主要目的在于个人学习与记录,如果能够有幸帮助到同样在修行的同僚那自然是件幸事,引用还望注明出处。笔者在写作过程中也会大量的阅读各种文章以增强理解,当然,会尽最大可能去注明文章引用,如果存在问题,希望指正。</p>
<hr>
<h1 id="二、正篇"><a href="#二、正篇" class="headerlink" title="二、正篇"></a>二、正篇</h1><p> 对于学习新东西,我的习惯一般都是先google或者baidu看大量的博客来给自己洗脑,让自己有一定的知识轮廓。接下来就会开始啃官方文档,或者阅读刚刚浏览过的博客中推荐的各种书籍。当然,如果有个不错的视频教程让自己快进着点一点最好不过了,很多效果一目了然。</p>
<p> 在stackoverflow上,有人给出了不错的<a href="http://stackoverflow.com/a/388282" target="_blank" rel="external">书籍大纲</a>,这些对于积累知识的初学者更有益。对于那些对于传统c++已经很熟悉,只是希望快速的了解c++11的新特性,并择机使用的选手来说,实验楼的<a href="https://www.shiyanlou.com/courses/605/labs/2022/document" target="_blank" rel="external">《C++ 11/14 高速上手教程》</a>免费在线课程可能会更有帮助。</p>
<p> 本文主要基于实验楼的课程大纲进行整理,并进行部分知识点的拓展完善。</p>
<h2 id="2-1-弃用-deprecated-特性"><a href="#2-1-弃用-deprecated-特性" class="headerlink" title="2.1 弃用(deprecated)特性"></a>2.1 弃用(deprecated)特性</h2><p> c++11提及到部分弃用特性。这里弃用并不等于废除并从标准中移除,而是警醒程序员在使用c++的时候能够意识到某些特性应避免使用。其实可能为了保证兼容性,这些特性可能永远不会被剔除出去(通常情况下是在编译的时,会显示一个弃用的warning),依旧可以被使用。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">lennybai@lennybai:~/Desktop/cpp11$ g++ main.cpp -std=c++11</div><div class="line">main.cpp: In <span class="keyword">function</span> ‘int main()’:</div><div class="line">main.cpp:7:15: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]</div><div class="line"> char* a = <span class="string">"hello world"</span>;</div></pre></td></tr></table></figure></p>
<p> 但是我们应该尽量遵循语言的发展与变迁,适当的改变自己对语言的使用方式。一个不恰当的例子,就好比黑白彩电置于当今社会,依然可以被使用,但是有更好的选择时为什么不去尝试呢?</p>
<h3 id="2-1-1-被移除或者弃用的特性"><a href="#2-1-1-被移除或者弃用的特性" class="headerlink" title="2.1.1 被移除或者弃用的特性"></a>2.1.1 被移除或者弃用的特性</h3><blockquote>
<ul>
<li>std::auto_ptr 被 std::unique_ptr 取代。</li>
<li>exception specifications</li>
<li>bool 类型的 ++ 操作被弃用。</li>
<li>export: 用法已被去掉,但关键字还是被保留了,给将来可能的特性使用</li>
<li>函数对象的基类(std::unary_function, std::binary_function)、函数指针适配器、类型成员指针适配器以及绑定器 (binder)。</li>
<li><a href="http://www.cnblogs.com/dolphin0520/archive/2011/04/20/2022330.html" target="_blank" rel="external">顺序点</a> (sequence point): 这个术语正被更为易懂的描述所取代。一个运算可以发生 (is sequenced before) 在另一个运算之前; 又或者两个运算彼此之间没有顺序关系 (are unsequenced)。</li>
</ul>
</blockquote>
<p> 就像前面提到的,被弃用的特性应该引起一定的重视。这里主要参考维基百科上面提到的内容列出了一些已经被弃用的特性。在以后的学习过程中也会不断完善这一部分。</p>
<h2 id="2-2-新特性"><a href="#2-2-新特性" class="headerlink" title="2.2 新特性"></a>2.2 新特性</h2><p> 对于c++11的新特性应该是阅读本文的客官们更关心的。c++11新特性包括但不完全是:lambda表达式,类型推断关键字auto、decltype和对模板的大量改进。在这一章节我们进行详细阐述。</p>
<h3 id="2-2-1-自动类型推断(auto-decltype)"><a href="#2-2-1-自动类型推断(auto-decltype)" class="headerlink" title="2.2.1 自动类型推断(auto/decltype)"></a>2.2.1 自动类型推断(auto/decltype)</h3><p> 对于传统c++而言,变量的类型都必须明确定义。虽然已经习惯传统c++编程的朋友们在声明或者定义基本类型(如int、char等)的变量时,并没有太多不妥的感觉。然而,可能也会在使用复杂模板时,觉得代码有点又丑又长。比如常见的迭代器声明:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> ( <span class="built_in">map</span> < <span class="keyword">int</span>,UserDefClass<userDefTemptype> >::iterator itr= userMap.begin(); itr !=userMap.end(); ++itr)</div></pre></td></tr></table></figure></p>
<p> 这里我列出了一个比较夸张的例子,目的是希望指出自动类型推断存在的意义。它其实已经很普遍的存在于现代编程语言之中(如python, javascript等脚本语言)。而在c++11中,通过对传统c++中auto关键字的修改得到自动类型推断的支持。<br> auto关键字在传统c++中用来指定存储期,一般用于指明具有自动生命周期的变量。最常见的就是函数内的局部变量。编译器在做编译时,对一般不是static修饰的变量,则默认赋予auto类型,所以auto关键字几乎很少被使用。在传统c++中,auto关键字的使用方法如下:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">auto</span> <span class="keyword">int</span> a;</div></pre></td></tr></table></figure></p>
<p> 而在c++11中,auto的功能变为了类型自动推断,编译器会根据初始代码推断所声明变量的真实类型。将类型判断的工作由程序员交给了编译器,这样,在一定程度提高了代码开发的效率。而且,大部分情况下会直观的发现,代码变的更简短(当然int类型还是要比auto少一个字符)。这里是使用auto对上面繁重代码的优化:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> ( <span class="keyword">auto</span> itr= userMap.begin(); itr !=userMap.end(); ++itr)</div></pre></td></tr></table></figure></p>
<p> 有没有很酷!接下来我们来看一下auto的具体使用,来更详细的了解一下它的功能。同时,也要学习一下它的使用规则。auto在c++11中,最容易理解的使用方式莫过于变量定义时的类型推断:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">auto</span> a = <span class="number">10</span>;</div><div class="line"><span class="keyword">auto</span> b = <span class="string">'A'</span>;</div><div class="line"><span class="function"><span class="keyword">auto</span> <span class="title">c</span><span class="params">(<span class="string">"hello"</span>)</span></span>;</div><div class="line"><span class="built_in">cout</span> << <span class="string">"a:"</span> << <span class="keyword">typeid</span>(a).name() << <span class="built_in">endl</span>; <span class="comment">// “a:i”</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"b:"</span> << <span class="keyword">typeid</span>(b).name() << <span class="built_in">endl</span>; <span class="comment">// "b:c"</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"c:"</span> << <span class="keyword">typeid</span>(c).name() << <span class="built_in">endl</span>; <span class="comment">// "c:PKc"</span></div></pre></td></tr></table></figure></p>
<p> 这里我们可以看到,对于变量可以不用明确的去定义其类型,而是用auto代替。其最终效果与传统c++的变量定义效果没有差别。这里可以通过typeid函数进行验证(#include< typeinfo >).<br> 在很多对于auto的讲解中,它常常被称作占位符。所谓占位符,我的理解是它不能像数据类型那样去声明一个变量。所以使用auto的变量必须进行初始化。理所当然的,也就不能使用c++类型转化将变量转换为auto类型。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">auto</span> a; <span class="comment">//error: declaration of ‘auto a’ has no initializer</span></div><div class="line"></div><div class="line"><span class="keyword">int</span> value1 = <span class="number">10</span>;</div><div class="line"><span class="keyword">auto</span> value2 = (<span class="keyword">auto</span>)value1; <span class="comment">// error: invalid use of ‘auto’</span></div><div class="line"><span class="keyword">auto</span> value3 = <span class="keyword">static_cast</span><<span class="keyword">auto</span>>(value1); <span class="comment">// error: invalid use of ‘auto’</span></div></pre></td></tr></table></figure></p>
<p> c++11已经彻底废弃了原有auto的使用方式,如代码所示:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">auto</span> <span class="keyword">int</span> a = <span class="number">10</span>; <span class="comment">//error: two or more data types in declaration of ‘a’</span></div></pre></td></tr></table></figure></p>
<p> auto可以接受c++的变量名表列的方式定义多个变量,但所有变量应具有相同的数据类型。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">auto</span> a1=<span class="number">10</span>, a2=<span class="number">20</span>, a3=<span class="number">30</span>;</div><div class="line"><span class="keyword">auto</span> a4=<span class="number">10</span>, a5=<span class="number">20.0</span>, a6 = <span class="string">'A'</span>; <span class="comment">// error: conflicting declaration</span></div></pre></td></tr></table></figure></p>
<p> auto在初始化时,会自动去除引用、const、volatile的语意。这种说法可能很难理解。其实就是如果原始变量为引用、const、volatile类型,auto初始化时需要自行指明。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="keyword">int</span> refa = <span class="number">10</span>;</div><div class="line"><span class="keyword">int</span> &refb = refa;</div><div class="line"><span class="keyword">auto</span> refc = refb;</div><div class="line"><span class="keyword">auto</span> &refd = refb;</div><div class="line">refa = <span class="number">100</span>;</div><div class="line"><span class="built_in">cout</span> << <span class="string">"refa: "</span> << <span class="keyword">typeid</span>(refa).name() << <span class="string">" "</span> << refa << <span class="built_in">endl</span>; <span class="comment">// 100</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"refb: "</span> << <span class="keyword">typeid</span>(refb).name() << <span class="string">" "</span> << refb << <span class="built_in">endl</span>; <span class="comment">// 100</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"refc: "</span> << <span class="keyword">typeid</span>(refc).name() << <span class="string">" "</span> << refc << <span class="built_in">endl</span>; <span class="comment">// 10</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"refd: "</span> << <span class="keyword">typeid</span>(refd).name() << <span class="string">" "</span> << refd << <span class="built_in">endl</span>; <span class="comment">// 100</span></div><div class="line"></div><div class="line"><span class="keyword">int</span> arrA[<span class="number">3</span>] = { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> };</div><div class="line"><span class="keyword">auto</span> arrB = arrA;</div><div class="line"><span class="keyword">auto</span> &refArrB = arrA;</div><div class="line"><span class="built_in">cout</span> << <span class="string">"arrA: "</span> << <span class="keyword">typeid</span>(arrA).name() << <span class="built_in">endl</span>; <span class="comment">// A3_i</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"arrB: "</span> << <span class="keyword">typeid</span>(arrB).name() << <span class="built_in">endl</span>; <span class="comment">//Pi</span></div><div class="line"><span class="built_in">cout</span> << <span class="string">"refArrB: "</span> << <span class="keyword">typeid</span>(refArrB).name() << <span class="built_in">endl</span>; <span class="comment">// A3_i</span></div></pre></td></tr></table></figure></p>
<p> auto关键字不仅可以配合变量使用,它在对传统c++函数的代码优化上也可以说是大放异彩。特别是针对那些具有模板类型的函数,更是让我们在编写时变的简单高效。我们来看第一个例子。这里我们在模板函数中使用auto定义了一个站位变量。这样就使得该变量在随着传入值的类型发生变化时,自动进行类型转换。是不是很方便。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> _Tx,<span class="keyword">typename</span> _Ty></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(_Tx x, _Ty y)</span></span></div><div class="line">{</div><div class="line"> <span class="keyword">auto</span> v = x*y;</div><div class="line"> <span class="built_in">cout</span> << v << <span class="built_in">endl</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">//call func</span></div><div class="line">func3(<span class="number">1</span>,<span class="number">2</span>); <span class="comment">// 2</span></div><div class="line">func3(<span class="number">1.1</span>,<span class="number">2.2</span>); <span class="comment">// 2.42</span></div></pre></td></tr></table></figure>
<p> auto关键字可以在函数中使用,那我们自然会想到,它能不能作为函数的返回值占位符。c++11自然提供了这种机制。但是用法可能和我们预期有一定的差距。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">auto func(int x, int y)->int</div><div class="line">{</div><div class="line"> return x+y;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 在c++11中,这样的返回值看起来很奇葩。使用auto来标注函数返回值时,还需要在末尾指定返回类型。会不会觉得还不如不用auto类型。但我觉得制定标准的人肯定也会考虑到这个问题。自然就去搜索了一些相关内容:</p>
<ol>
<li>在函数返回值特别长的时候放在末尾,会显得好看。</li>
<li>c++14会把返回值去掉,让编译器直接支持自动推倒(c++14确实是做到了)</li>
<li>出现在函数后面的表达式在代码编译时也是出现在函数之后的,这就使得很多函数中的临时变量可以出现在这个表达式中。这个我们在后面的decltype使用中可以看到效果。(显然,这个才是我认为最重要的)</li>
</ol>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//c++14 支持</span></div><div class="line"><span class="function"><span class="keyword">auto</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span></span></div><div class="line">{</div><div class="line"> <span class="keyword">return</span> x+y;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 这种auto作为函数返回值占位符的用法,会使编写复杂的模板函数时变得相当简单和灵活。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">template <typename _Tx, typename _Ty></div><div class="line">auto func(_Tx x, _Ty y) -> decltype(x*y)</div><div class="line">{</div><div class="line"> return x*y;</div><div class="line">}</div><div class="line"></div><div class="line">//call func</div><div class="line">auto funcA = func(1,2);</div><div class="line">cout << funcA << endl; // 2</div><div class="line">funcA = func(1.1,2.2);</div><div class="line">cout << funcA << endl; // 2</div><div class="line">auto funcB = func(1.1,2.2);</div><div class="line">cout << funcB << endl; // 2.42</div></pre></td></tr></table></figure>
<p> 这里用到了decltype(declared type),它可以用来通过传入的参数来声明类型。这样func这个模板函数的会很方便的随着模板传入类型来自动改变返回值类型。bravo!</p>
<p> decltype不存在太多的歧义,这里直接列出代码。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">int declint = 10;</div><div class="line">decltype(declint) declintt;</div><div class="line"></div><div class="line">vector<int> vec;</div><div class="line">typedef decltype(vec.begin()) vectype;</div><div class="line"></div><div class="line">decltype(declint) temp1 = declint;</div><div class="line">decltype((declint)) temp2 = declint; //decltype(())定义的是引用类型</div><div class="line">decltype((declint)) temp3; // error: ‘temp3’ declared as reference but not initialized</div></pre></td></tr></table></figure>
<p> 接下来我们说一下刚才我们提到的函数返回类型后置的问题。我们已经知道通过decltype可以根据传入参数获取最终的数据类型。那么我们将下面代码进行修改:</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">// origin, ok~</div><div class="line">template <typename _Tx, typename _Ty></div><div class="line">auto func(_Tx x, _Ty y) -> decltype(x*y)</div><div class="line">{</div><div class="line"> return x*y;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 一般想法是认为,返回值不就是decltype(x*y)类型么? 那我们直接放前面不是更方便。好的,我们改写一下.</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// update</span></div><div class="line"><span class="keyword">template</span> <<span class="keyword">typename</span> _Tx, <span class="keyword">typename</span> _Ty></div><div class="line"><span class="keyword">decltype</span>(x*y) func(_Tx x, _Ty y)</div><div class="line">{</div><div class="line"> <span class="keyword">return</span> x*y;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 然而:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">lennybai@lennybai:~/project/cpp11$ g++ main.cpp -std=c++11</div><div class="line">main.cpp:16:10: error: ‘x’ was not declared <span class="keyword">in</span> this scope</div><div class="line"> decltype(x*y) func4(_Tx x, _Ty y)</div><div class="line"> ^</div><div class="line">main.cpp:16:10: error: ‘x’ was not declared <span class="keyword">in</span> this scope</div><div class="line">main.cpp:16:12: error: ‘y’ was not declared <span class="keyword">in</span> this scope</div><div class="line"> decltype(x*y) func4(_Tx x, _Ty y)</div><div class="line"> ^</div></pre></td></tr></table></figure>
<p> 是的,结果就是这么神奇。这也说明 ’function->expr‘ 中的expr是出现在函数之后的。如果不使用auto占位符,而直接使用decltype(x*y)声明函数类型。由于x,y在函数运行前尚未明确类型,所以这里就会出现编译错误。</p>
<p> 在这一小节最后需要指出的是,auto是不能作为参数占位符出现的。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 客官不可以哦</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func2</span><span class="params">(<span class="keyword">auto</span> x)</span></span></div><div class="line">{</div><div class="line"> <span class="comment">//do something</span></div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="2-2-2-指针空值nullptr"><a href="#2-2-2-指针空值nullptr" class="headerlink" title="2.2.2 指针空值nullptr"></a>2.2.2 指针空值nullptr</h3><p> 在传统c++中,通常使用NULL来标识空指针。NULL通常是一个与0相关的宏定义。这里是/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h中对NULL的定义。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">if</span> defined (_STDDEF_H) || defined (__need_NULL)</span></div><div class="line"><span class="meta">#<span class="meta-keyword">undef</span> NULL <span class="comment">/* in case <stdio.h> has defined it. */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> __GNUG__</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NULL __null</span></div><div class="line"><span class="meta">#<span class="meta-keyword">else</span> <span class="comment">/* G++ */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> __cplusplus</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NULL ((void *)0)</span></div><div class="line"><span class="meta">#<span class="meta-keyword">else</span> <span class="comment">/* C++ */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> NULL 0</span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* C++ */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* G++ */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">/* NULL not defined and <stddef.h> or need NULL. */</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">undef</span> __need_NULL</span></div></pre></td></tr></table></figure></p>
<p> 我们发现在传统C++中,NULL被定义为0。由于没有类型限制,它可以被强制转换为各种其他数据类型。最常见的例子就是当出现函数重载时会发生混乱。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> n)</span> </span>{ <span class="built_in">cout</span> << <span class="string">"call func(int n) : "</span> << <span class="built_in">endl</span>; };</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> *p)</span> </span>{ <span class="built_in">cout</span> << <span class="string">"call func(int *p) : "</span> << <span class="built_in">endl</span>; };</div><div class="line"></div><div class="line">func(<span class="literal">NULL</span>); <span class="comment">// error: call of overloaded ‘func(NULL)’ is ambiguous</span></div></pre></td></tr></table></figure></p>
<p> 为了区分不同类型的空指针,C++11引入了nullptr_t类型的指针空值nullptr。它可以自动隐性的转换为所需的成员指针或者函数指针的类型。从而使程序更加清晰明了。值得注意的是,nullptr只能用来标识指针类型。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> n)</span> </span>{ <span class="built_in">cout</span> << <span class="string">"call func(int n) : "</span> << <span class="built_in">endl</span>; };</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> *p)</span> </span>{ <span class="built_in">cout</span> << <span class="string">"call func(int *p) : "</span> << <span class="built_in">endl</span>; };</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">{</div><div class="line"> <span class="keyword">int</span> nIntNull = <span class="literal">NULL</span>; <span class="comment">// ok</span></div><div class="line"> <span class="keyword">int</span> *pIntNull = <span class="literal">NULL</span>; <span class="comment">// ok</span></div><div class="line"> <span class="keyword">int</span> *pIntNullptr = <span class="literal">nullptr</span>; <span class="comment">// ok</span></div><div class="line"> <span class="keyword">int</span> nIntNullptr = <span class="literal">nullptr</span>; <span class="comment">// error: cannot convert ‘std::nullptr_t’ to ‘int’ in initialization</span></div><div class="line"></div><div class="line"> func(<span class="literal">NULL</span>); <span class="comment">// error: call of overloaded ‘func(NULL)’ is ambiguous</span></div><div class="line"> func(<span class="literal">nullptr</span>); <span class="comment">// call func(int *p)</span></div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h3 id="2-2-3-常量区分符constexpr"><a href="#2-2-3-常量区分符constexpr" class="headerlink" title="2.2.3 常量区分符constexpr"></a>2.2.3 常量区分符constexpr</h3><p> 常量表达式在c++中还是很常见的,特别是在数组或者容器等初始化时传入的大小通常为常量表达式。在C++中,常量表达式通常被解释为在编译时可以明确其值的表达式。最常见的常量表达式就是被const标识的变量:<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">int</span> n = <span class="number">1</span>;</div><div class="line"><span class="built_in">std</span>::<span class="built_in">array</span><<span class="keyword">int</span>, n> a1; <span class="comment">// error, n is not a constant expression</span></div><div class="line"><span class="keyword">const</span> <span class="keyword">int</span> cn = <span class="number">2</span>;</div><div class="line"><span class="built_in">std</span>::<span class="built_in">array</span><<span class="keyword">int</span>, cn> a2; <span class="comment">// OK, cn is a constant expression</span></div></pre></td></tr></table></figure></p>
<p> 其实,在我们进行程序设计的时候,常常会发现很多情况是需要根据运行情况去获取一个值,然后再进行数据或者容器大小的分配。而这些值我们在给定条件值之后,很容易就会被推导出来。而对于计算机来说,却需要在每次运行时不断重复相同的推倒工作。那么我们可能会觉得,如果可以像常量表达式那样在编译时就确定其值,是不是在运行时就可以得到更高的运行效率呢。c++为我们提供了常量区分符constexpr来实现这一效果。<br> constexpr用来标示一个变量或者函数为常量表达式,也是告诉编译器需要去验证它们是不是一个常量表达式。<br><figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div></pre></td><td class="code"><pre><div class="line">int x;</div><div class="line">struct A {</div><div class="line"> constexpr A(bool b) : m(b?42:x) { }</div><div class="line"> int m;</div><div class="line">};</div><div class="line">constexpr int v = A(true).m; // OK</div><div class="line">constexpr int w = A(false).m; // error: non-const x</div><div class="line">constexpr int mf = 20; // 20是常量表达式</div><div class="line">constexpr int limit = mf + 1; // mf + 1是常量表达式</div><div class="line">constexpr int sz = size(); // 只有当size是一个constexpr函数时才是一条正确的声明语句</div><div class="line"></div><div class="line">constexpr int A()</div><div class="line">{</div><div class="line"> return 10;</div><div class="line">}</div><div class="line"></div><div class="line">constexpr int fibonacci1(const int n) {</div><div class="line"> return n == 1 || n == 2 ? 1 : fibonacci1(n-1)+fibonacci1(n-2);</div><div class="line">}</div><div class="line"></div><div class="line">// c++11 error error: body of constexpr function ‘constexpr int fibonacci2(int)’ not a return-statement</div><div class="line">// c++14 OK</div><div class="line"> constexpr int fibonacci2(const int n) {</div><div class="line"> if(n == 1) return 1;</div><div class="line"> if(n == 2) return 1;</div><div class="line"> return fibonacci2(n-1)+fibonacci2(n-2);</div><div class="line">}</div><div class="line"></div><div class="line">int i1 = 10;</div><div class="line">const int i2 = i1;</div><div class="line">const int i3 = 10;</div><div class="line">constexpr int x1 = i1; // error: the value of ‘i1’ is not usable in a constant expression</div><div class="line">constexpr int x2 = i2; // error: the value of ‘i2’ is not usable in a constant expression</div><div class="line">constexpr int x3 = i3; // ok</div><div class="line">constexpr int x4 = 10; // ok</div><div class="line">constexpr int x5 = A(); // ok</div><div class="line">constexpr int x6 = fibonacci1(10); // ok</div><div class="line">constexpr int x7 = cin.get(); // !error</div><div class="line">constexpr int x8 = fibonacci2(10);</div><div class="line"></div><div class="line">int a[i2]; // ok</div><div class="line">int b[x4]; // ok</div></pre></td></tr></table></figure></p>
<p> 从上面的代码中我们可以大概了解到constexpr的作用与用法。这里以上代码进行一些说明:</p>
<ol>
<li>c++11中对constexpr修饰的函数只能直接返回常量表达式。c++14中进行了增强,它可以支持局部变量和条件语句等。</li>
<li><p>const int i2为运行时赋值,所以x2 = i2 报错; const int i3为常量表达式,所以x3=i3没问题</p>
<p> 对于constexpr可以在这里<a href="http://cpptruths.blogspot.jp/2011/07/want-speed-use-constexpr-meta.html" target="_blank" rel="external">了解更多</a>。</p>
</li>
</ol>
<h3 id="2-2-4-range-based-for-loop"><a href="#2-2-4-range-based-for-loop" class="headerlink" title="2.2.4 range-based for loop"></a>2.2.4 range-based for loop</h3><p> 在cppreference中,这个特性被描述为:</p>
<blockquote>
<p>Executes a for loop over a range.Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container. </p>
</blockquote>
<p> <br> 这个描述有些官方和笼统。其实,range-based for loop在c++11中加入,它使得c++开始支持类似于’foreach’的范式格式。这种新格式使得我们获取或者操作数组时变得更容易,前提是我们不去关心索引,迭代器和数量的前提下。range-based for loop可以支持迭代所有的c类型数组,初始化列表和重载了begin()和end()函数的容器。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><map></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><vector></span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></div><div class="line">{</div><div class="line"> <span class="built_in">map</span><<span class="built_in">string</span>, <span class="built_in">vector</span><<span class="keyword">int</span>>> m;</div><div class="line"> <span class="built_in">vector</span><<span class="keyword">int</span>> v;</div><div class="line"> v.push_back(<span class="number">1</span>);</div><div class="line"> v.push_back(<span class="number">2</span>);</div><div class="line"> v.push_back(<span class="number">3</span>);</div><div class="line"> m[<span class="string">"my_vector"</span>] = v;</div><div class="line"></div><div class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span>& tempM : m)</div><div class="line"> {</div><div class="line"> <span class="built_in">cout</span> << tempM.first << <span class="built_in">endl</span>;</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">auto</span>& tempV : tempM.second)</div><div class="line"> {</div><div class="line"> <span class="built_in">cout</span> << tempV << <span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">int</span> arr[] = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>};</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span>& e : arr)</div><div class="line"> {</div><div class="line"> <span class="built_in">cout</span> << e << <span class="built_in">endl</span>;</div><div class="line"> e = e*e;</div><div class="line"> }</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">int</span>& e : arr)</div><div class="line"> {</div><div class="line"> <span class="built_in">cout</span> << e << <span class="built_in">endl</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="2-2-5-快速初始化列表"><a href="#2-2-5-快速初始化列表" class="headerlink" title="2.2.5 快速初始化列表"></a>2.2.5 快速初始化列表</h3><p> 在c++11中,它提供了更便捷,或者说是更人性化的初始化方式。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//c++ 98 error: in C++98 ‘m’ must be initialized by constructor, not by ‘{...}’</span></div><div class="line"><span class="comment">//c++ 11</span></div><div class="line"><span class="built_in">vector</span><<span class="keyword">int</span>> v = {<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>};</div><div class="line"><span class="built_in">cout</span> << v[<span class="number">3</span>] << <span class="built_in">endl</span>;</div><div class="line"></div><div class="line"><span class="comment">//c++98 error: could not convert ‘{{1, 2}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<int, int>’</span></div><div class="line"><span class="comment">//c++11 ok</span></div><div class="line"><span class="built_in">map</span><<span class="keyword">int</span>, <span class="keyword">int</span>> m = {{<span class="number">1</span>,<span class="number">2</span>}};</div><div class="line"><span class="built_in">cout</span> << m[<span class="number">1</span>] << <span class="built_in">endl</span>;</div></pre></td></tr></table></figure></p>
<p> 对于对象的内部属性初始化,我们可以通过调用参数为initializer_list的方法快速初始化。<br><figure class="highlight c++"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">struct</span> myclass {</div><div class="line"> myclass (<span class="keyword">int</span>,<span class="keyword">int</span>);</div><div class="line"> myclass (<span class="built_in">initializer_list</span><<span class="keyword">int</span>>);</div><div class="line"> <span class="comment">/* definitions ... */</span></div><div class="line">};</div><div class="line"></div><div class="line">myclass foo {<span class="number">10</span>,<span class="number">20</span>}; <span class="comment">// calls initializer_list ctor</span></div><div class="line"><span class="function">myclass <span class="title">bar</span> <span class="params">(<span class="number">10</span>,<span class="number">20</span>)</span></span>; <span class="comment">// calls first constructor</span></div></pre></td></tr></table></figure></p>
<h3 id="2-2-6-类型别名"><a href="#2-2-6-类型别名" class="headerlink" title="2.2.6 类型别名"></a>2.2.6 类型别名</h3><p> 传统c++同常使用typedef为类型定义一个新的名称。给函数声明去做个别名是比较常见的使用方式。</p>
<blockquote>
<p>typedef void (*SigHandler)(int);</p>
</blockquote>
<p> 这个是unix中信号处理的圆形函数。它讲一个参数为int并返回值为void的函数原型重命名为SigHandler.这个原型相对还比较容易理解。但在我们平时的编程过程中,遇到的情况往往比这要复杂得多。c++11为我们提供了一个更符合人类思维和更直观的表述方式(这话是我自己说的,不要追究责任233333)。</p>
<blockquote>
<p>using SigHandler = void(*)(int);</p>
</blockquote>
<p> 这里就提高了using关键字。在传统c++中,对于using 我们可能唯一的用法就是using namespace。而在c++11中,它获得了更多的功能。下面我们继续说一些其他的别名使用情况。提到类型别名,我们有的时候会想到,能不能讲某些又臭又长的模板类型给做个别名。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> X, <span class="keyword">typename</span> Y, <span class="keyword">typename</span> Z></div><div class="line"><span class="keyword">class</span> MyTest</div><div class="line">{</div><div class="line"> <span class="keyword">public</span>:</div><div class="line"> MyTest();</div><div class="line"> <span class="keyword">virtual</span> ~MyTest();</div><div class="line"> <span class="keyword">private</span>:</div><div class="line"> X x;</div><div class="line"> Y y;</div><div class="line"> Z z;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> U></div><div class="line"><span class="keyword">typedef</span> MyTest<<span class="keyword">int</span>,U,<span class="keyword">int</span>> mm; <span class="comment">//error: template declaration of ‘typedef’</span></div></pre></td></tr></table></figure></p>
<p> 在传统c++中,它并不支持对上述初始化部分类型的模板类进行再次重命名。而c++11中可以通过using关键字得到实现。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">template</span><<span class="keyword">typename</span> U></div><div class="line"><span class="keyword">using</span> mm = MyTest<<span class="keyword">int</span>,U,<span class="keyword">int</span>>;</div></pre></td></tr></table></figure></p>
<hr>
<h1 id="3-参考文献"><a href="#3-参考文献" class="headerlink" title="3 参考文献"></a>3 参考文献</h1><ul>
<li>[1]: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf" target="_blank" rel="external">c++标准</a></li>
<li>[2]: <a href="http://en.cppreference.com/w/cpp/types/NULL" target="_blank" rel="external">cppreference</a></li>
<li>[3]: <a href="http://www.codeproject.com/Articles/570638/Ten-Cplusplus-Features-Every-Cplusplus-Developer" target="_blank" rel="external">Ten C++11 Features Every C++ Developer Should Use</a></li>
</ul>
]]></content>
</entry>
</search>