-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
651 lines (383 loc) · 90 KB
/
index.html
File metadata and controls
651 lines (383 loc) · 90 KB
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
<!DOCTYPE HTML>
<html>
<head >
<meta charset="utf-8">
<title>whb blog | stay hungry stay foolish</title>
<meta name="author" content="whb">
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta property="og:site_name" content="whb blog"/>
<meta property="og:image" content="/favicon.ico"/>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-5005349780815724",
enable_page_level_ads: true
});
</script>
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?223eea22355699157e147870eb124b24";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<link rel="manifest" href="/manifest.json">
<link href="/favicon.ico" rel="icon">
<link rel="alternate" href="/atom.xml" title="whb blog" type="application/atom+xml">
<link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/base/bootstrap.min.css" media="screen" type="text/css">
<link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">
</head>
<body>
<div class="blog">
<div class="content">
<header class="header-container" style="background-image: url('/images/blog-bg.jpg');">
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header page-scroll">
<button type="button" id="tglBtn" class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">whb</a>
</div>
<div id="bosenyblog-navbar">
<div class="navbar-collapse" id="bs-example-navbar-collapse-6">
<ul class="nav navbar-nav navbar-right">
<li><a href="/">Home</a></li>
<li><a href="/archives">Archives</a></li>
<li><a href="/about">About</a></li>
<li><a href="/tags">Tags</a></li>
</ul>
</div>
</div>
</div>
</nav>
<div class="gotop-btn">
</div>
</header>
<div class="container ">
<div class="row">
<main class="site-main posts-loop col-lg-8 col-lg-offset-1
col-md-8 col-md-offset-1
col-sm-12
col-xs-12">
<article class="article-container ">
<h3 class="article-title"><a href="/2020/06/14/c++ 函数重载和const/"><span>c++ 函数重载和const</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2020/06/14/c++ 函数重载和const/" rel="bookmark">
<time class="entry-date published" datetime="2020-06-14T15:14:45.584Z">
2020-06-14
</time>
</a>
</span>
<br />
</div>
<div class="article-content">
<div class="entry">
<h1 id="c-函数重载和const以及拷贝构造函数的重载"><a href="#c-函数重载和const以及拷贝构造函数的重载" class="headerlink" title="c++ 函数重载和const以及拷贝构造函数的重载"></a>c++ 函数重载和const以及拷贝构造函数的重载</h1><p> 观察到拷贝构造函数的参数类型为const引用,想想是否其是否能够重载,通过学习,总结一下关于const在函数中的重载。</p>
<h2 id="常成员函数和非常成员函数之间的重载:"><a href="#常成员函数和非常成员函数之间的重载:" class="headerlink" title="常成员函数和非常成员函数之间的重载:"></a>常成员函数和非常成员函数之间的重载:</h2><p>常成员函数:</p>
<p>声明:<类型标志符> 函数名(参数表) const;</p>
<p>说明:</p>
<ul>
<li>const是函数类型的一部分,在实现部分也要带该关键字</li>
<li>const关键字是可以用于对重载函数区分</li>
<li>常成员函数不能更新类的成员变量,也不能调用类中没有const修饰的成员函数,只能调用常成员函数</li>
<li>非常量对象也可以调用常成员函数,但是如果有重载的非成员函数则会调用非常成员函数</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span>{</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> A(<span class="keyword">int</span> a):x(a){}</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">getX</span><span class="params">()</span> <span class="keyword">const</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"const version"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> x;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">int</span> <span class="title">getX</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"non const version"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> x;</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="keyword">int</span> x;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="function">A <span class="title">a</span><span class="params">(<span class="number">4</span>)</span></span>;</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << a.getX() << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="function"><span class="keyword">const</span> A <span class="title">b</span><span class="params">(<span class="number">3</span>)</span></span>;</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << b.getX() << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="const修饰成员函数形参时的重载:"><a href="#const修饰成员函数形参时的重载:" class="headerlink" title="const修饰成员函数形参时的重载:"></a>const修饰成员函数形参时的重载:</h2><p>这时候分为两种情况,一种情况不允许重载,另一个允许。const在函数中的含义是该值在此函数范围内“无法修改”。站在调用者的角度,所有的值传递都是无法修改实参的。所以,如果两个函数在调用者看来,是语义相同的,不能构成重载。反之两个函数一个可以修改实参一个不可以则构成重载</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">const</span> <span class="keyword">int</span> i)</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"const version & i ="</span> << i << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span> i)</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"non-const version & i ="</span><< i << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">int</span> i =<span class="number">3</span>;</span><br><span class="line"> func(i);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>结果显示编译错误:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">main.cpp: In function ‘void <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">int</span>)</span>’:</span></span><br><span class="line">main.cpp:<span class="number">31</span>:<span class="number">6</span>: error: redefinition of ‘void <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">int</span>)</span>’</span></span><br><span class="line"> void <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">int</span> i)</span></span>{</span><br><span class="line"> ^</span><br><span class="line">main.cpp:<span class="number">27</span>:<span class="number">6</span>: error: ‘void <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">int</span>)</span>’ <span class="title">previously</span> <span class="title">defined</span> <span class="title">here</span></span></span><br><span class="line"> void <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">const</span> <span class="keyword">int</span> i)</span></span>{</span><br></pre></td></tr></table></figure>
<p>void func(int i)和 void func(const int i);</p>
<p>实际上没有区别,因为函数调用的时候,存在形实结合的过程,所以不管有没有const都不会改变实参的值</p>
<p>但是也有能够重载的情况,比如:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* i)</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"const version & i ="</span> << i << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">char</span>* i)</span></span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"non-const version & i ="</span><< i << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span>* str=<span class="string">"hello world"</span>;</span><br><span class="line"> func(str);</span><br><span class="line"> <span class="keyword">char</span>* str1 =<span class="string">"hello fuck"</span>;</span><br><span class="line"> func(str1);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>这种情况和上面的有啥不一样呢?其实主要是 fun(char *a) 的char *a 中a指向的是一个字符串变量,而func(const char *a)的const char *a指向的是一个字符串常量,所以当参数为字符串常量时,调用第二个函数,而当函数是字符串变量时,调用第一个函数。</p>
<p>但是下面的程序却编译不过,因为其都是指向字符串常量。不同的是char *a是指针变量 而char *const a是指针常量,这就和int i和const int i的关系一样了,所以也会提示重定义</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string"><iostream> </span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>; </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">char</span> *a)</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"non-const fun() "</span> << a; </span><br><span class="line">} </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">char</span> * <span class="keyword">const</span> a)</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"const fun() "</span> << a; </span><br><span class="line">} </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="keyword">char</span> ptr[] = <span class="string">"hello world"</span>; </span><br><span class="line"> fun(ptr); </span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>最后关于引用, 比如int &i 和const int &i 也是可以重载的,原因时第一个i引用的是一个变量,而第二个i引用的是一个常量,两者是不一样的,类似于上面的指向变量的指针的指向常量的指针。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string"><iostream> </span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>; </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">const</span> <span class="keyword">int</span> &i)</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"fun(const int &) called "</span><<<span class="built_in">endl</span>; </span><br><span class="line">} </span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">int</span> &i)</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"fun(int &) called "</span><<<span class="built_in">endl</span> ; </span><br><span class="line">} </span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span></span><br><span class="line"><span class="function"></span>{ </span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">int</span> i = <span class="number">10</span>; </span><br><span class="line"> fun(i); </span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
<h3 class="article-read"><a href="/2020/06/14/c++ 函数重载和const/"><span>more</span></a></h3>
</article>
<article class="article-container ">
<h3 class="article-title"><a href="/2020/06/14/由stdcall_once引发的c++单例模式的总结/"><span>由stdcall_once引发的c++单例模式的总结</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2020/06/14/由stdcall_once引发的c++单例模式的总结/" rel="bookmark">
<time class="entry-date published" datetime="2020-06-14T14:28:57.418Z">
2020-06-14
</time>
</a>
</span>
<br />
</div>
<div class="article-content">
<div class="entry">
<h1 id="由std-call-once引发的c-单例模式的总结"><a href="#由std-call-once引发的c-单例模式的总结" class="headerlink" title="由std::call_once引发的c++单例模式的总结"></a>由std::call_once引发的c++单例模式的总结</h1><p> 由于学习c++并发编程这本书,书中提到可以使用std::call_once保证某函数只执行一次,所以将类的实例放到函数中去初始化,不就符合在多线程中单例模式的实现吗?想到这里,就想重温一下老的单例模式到底是如何实现的,也好跟现在的做做对比,加深理解。废话不多说,首先重温一下原来的单例模式到底是如何实现的吧?</p>
<h2 id="饿汉式:"><a href="#饿汉式:" class="headerlink" title="饿汉式:"></a>饿汉式:</h2><p>常规的单例模式的设计,仅仅能通过Instance方法得到类的实例(往往是引用或者指针,毕竟只有一个实例)。因此,第一要点考虑的就是禁止构造函数,拷贝构造和赋值函数。如果需要释放资源,一般不允许调用delete方法,最多对外提供release(或者Destroy)方法来释放内部资源。</p>
<p>下面是最简单的饿汉式实现方案:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton() =<span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton & ) =<span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"> ~singleton()=<span class="keyword">default</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton& <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">static</span> singleton _instance;</span><br><span class="line"> <span class="keyword">return</span> _instance;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>因为不能通过构造函数来得到类的实例,因此类的Instance方法必须是static(即绑定到类对象设计本身,不属于类实例的方法)。静态变量会在第一使用时初始化,多次调用会被编译器忽略,生命周期是程序的运行区间,并且是多线程安全的。因为静态局部变量分配在全局静态区,内存一直都在。</p>
<h4 id="返回指针类型:"><a href="#返回指针类型:" class="headerlink" title="返回指针类型:"></a>返回指针类型:</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singletonPoiner</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">singletonPoiner()=<span class="keyword">default</span>;</span><br><span class="line">~singletonPoiner()=<span class="keyword">default</span>;</span><br><span class="line">singletonPoiner(<span class="keyword">const</span> singletonPoiner&)= <span class="keyword">delete</span>;</span><br><span class="line">singletonPoiner& <span class="keyword">operator</span>=(<span class="keyword">const</span> singletonPoiner&)=<span class="keyword">delete</span>; </span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singletonPoiner* <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">static</span> singletonPoiner _instance;</span><br><span class="line"> <span class="keyword">return</span> &_instance;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h2 id="懒汉式:"><a href="#懒汉式:" class="headerlink" title="懒汉式:"></a>懒汉式:</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton()=<span class="keyword">default</span>;</span><br><span class="line"> ~singleton()=<span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton* <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> _pInstance = <span class="keyword">new</span> singleton;</span><br><span class="line"> <span class="keyword">return</span> _pInstance;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">static</span> singleton* _pInstance;</span><br><span class="line"> </span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>这是非常简单的懒汉式实现方式,即看看指针存在否,不存在new一下。但存在以下一些问题:</p>
<p>1、内存无法正常释放。</p>
<p>2、多线程不安全。</p>
<p>尽管如此,如果您的管理类的生命周期和程序一样长时,就可以不考虑内存泄露,毕竟操作系统会在程序退出时自动回收内存。</p>
<h4 id="优化版:"><a href="#优化版:" class="headerlink" title="优化版:"></a>优化版:</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><mutex></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton()=<span class="keyword">default</span>;</span><br><span class="line"> ~singleton()=<span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton&)=<span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton* <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> _pInstance = <span class="keyword">new</span> singleton;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> _pInstance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Destroy</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(_pInstance){</span><br><span class="line"> <span class="keyword">delete</span> _pInstance;</span><br><span class="line"> _pInstance = <span class="literal">nullptr</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="keyword">static</span> singleton* _pInstance;</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::mutex mtx;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>这里我们可以使用Double-checked locking pattern(DCLP)来减少锁的竞争机会,因为绝大数情况_pInstance都是非空的。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> singleton* <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> _pInstance = <span class="keyword">new</span> singleton;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> _pInstance;</span><br><span class="line"> </span><br><span class="line"> }</span><br></pre></td></tr></table></figure>
<p>尽管这个术语非常高大上,很多博客也会提及,但其实细究起来,它并不是线程安全的。</p>
<p>注意到_pInstance = new singleton(), 是一个写操作,前面有一个无锁的读操作。当真正的写操作进行时,前面的读操作存在脏读情况。</p>
<p>_pInstance = new singleton(), 表面上一个语句,展开后由</p>
<p>1、malloc 一块内存,地址复制到_pInstance</p>
<p>2、针对_pInstance 地址上调用placement new进行类的构造</p>
<p>当多线程情况下,一个线程有可能进行了一之后,另外一个线程进来后,判断非空,进行类对象的访问,导致crash。</p>
<p>如果这样写的项目没有遇到崩溃,大概率都是在main的某个地方提前实例化过了(如管理类很多有init方法,调用了就实例化了)</p>
<p>这个崩溃的概率非常小,需要多线程恰好同时调用Instance,并且某一个线程执行了malloc之后,分成时间片,另外一个线程拿到了未构造的类实例进行操作。</p>
<p>另外,优化后的单例还是有内存泄露的风险,用户可能忘记Destroy了,有时也不敢乱Destroy。想要自动管理内存释放?可以增加一个垃圾收集类。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><mutex></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton() = <span class="keyword">default</span>;</span><br><span class="line"> ~singleton() = <span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton&) = <span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) = <span class="keyword">delete</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton* <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> _pInstance = <span class="keyword">new</span> singleton;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> _pInstance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Destroy</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(_pInstance){</span><br><span class="line"> <span class="keyword">delete</span> _pInstance;</span><br><span class="line"> _pInstance = <span class="literal">nullptr</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">GarbageCollect</span>{</span></span><br><span class="line"> ~GarbageCollect(){</span><br><span class="line"> <span class="keyword">if</span>(_pInstance){</span><br><span class="line"> <span class="keyword">delete</span> _pInstance;</span><br><span class="line"> _pInstance = <span class="literal">nullptr</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="keyword">static</span> singleton *_pInstance;</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::mutex mtx;</span><br><span class="line"> <span class="keyword">static</span> GarbageCollect gc;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line">singleton* singleton::_pInstance;<span class="comment">//这个得放cpp中,不然编译报错,静态成员默认赋null。</span></span><br><span class="line"><span class="built_in">std</span>::mutex singleton::mtx;<span class="comment">//这个得放cpp中,不然编译报错,</span></span><br><span class="line">singleton::GarbageCollect singleton::gc;<span class="comment">//这个得放cpp中,不然编译报错,</span></span><br></pre></td></tr></table></figure>
<p>当然由于静态变量的空间在全局内存区,其空间的释放是在程序结束之后才进行释放的。而在程序结束时,系统会自动回收该程序申请的空间。</p>
<p>gc的析构函数在释放静态实例时,也是在程序结束时才会调用的。所以这里写的内存释放意义不大。当然对于那些在程序结束后不自动回收空间的系统,还是需要写空间回收的。</p>
<p>另外还可以使用智能指针来释放:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><mutex></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><memory></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton()=<span class="keyword">default</span>;</span><br><span class="line"> ~singleton()=<span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton&)=<span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton& <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> <span class="function"><span class="built_in">std</span>::lock_guard<<span class="built_in">std</span>::mutex> <span class="title">guard</span><span class="params">(mtx)</span></span>;</span><br><span class="line"> <span class="keyword">if</span>(!_pInstance){</span><br><span class="line"> _pInstance.reset(<span class="keyword">new</span> singleton);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> *_pInstance;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::<span class="built_in">unique_ptr</span><singleton> _pInstance;</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::mutex mtx;</span><br><span class="line">};</span><br><span class="line"><span class="built_in">std</span>::<span class="built_in">unique_ptr</span><singleton> singleton::_pInstance;<span class="comment">//这个得放cpp中,不然编译报错,</span></span><br><span class="line"><span class="built_in">std</span>::mutex singleton::mtx;<span class="comment">//这个得放cpp中,不然编译报错,</span></span><br></pre></td></tr></table></figure>
<p>这里使用shared_ptr也可以,不过shared_ptr占用的内存和内部复杂度稍大点。</p>
<p>推荐返回singleton&, 用了智能指针就得放弃裸指针。</p>
<p>最后,终于可以引出std::call_once再次优化以此去掉额外的锁了</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><mutex></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><memory></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">singleton</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> singleton()=<span class="keyword">default</span>;</span><br><span class="line"> ~singleton()=<span class="keyword">default</span>;</span><br><span class="line"> singleton(<span class="keyword">const</span> singleton&)=<span class="keyword">delete</span>;</span><br><span class="line"> singleton& <span class="keyword">operator</span>=(<span class="keyword">const</span> singleton&) =<span class="keyword">delete</span>;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> singleton& <span class="title">Instance</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::once_flag s_flag;</span><br><span class="line"> <span class="built_in">std</span>::call_once(s_flag, [&](){</span><br><span class="line"> _pInstance.reset(<span class="keyword">new</span> singleton);</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> *_pInstance;</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line"> <span class="keyword">static</span> <span class="built_in">std</span>::<span class="built_in">unique_ptr</span><singleton> _pInstance;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>可以看到std::call_once 可以去除掉互斥量</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
<h3 class="article-read"><a href="/2020/06/14/由stdcall_once引发的c++单例模式的总结/"><span>more</span></a></h3>
</article>
<article class="article-container ">
<h3 class="article-title"><a href="/2020/05/17/printf、sprinf即snprinf的格式化的使用/"><span>printf、sprinf即snprinf的格式化的使用</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2020/05/17/printf、sprinf即snprinf的格式化的使用/" rel="bookmark">
<time class="entry-date published" datetime="2020-05-17T08:02:11.060Z">
2020-05-17
</time>
</a>
</span>
<br />
</div>
<div class="article-content">
<div class="entry">
<h1 id="printf、sprinf即snprinf的格式化的使用"><a href="#printf、sprinf即snprinf的格式化的使用" class="headerlink" title="printf、sprinf即snprinf的格式化的使用"></a>printf、sprinf即snprinf的格式化的使用</h1><p>在平常的编程实践中,发现sprintf和snprintf的效率会比string类型的“+”的效率会高一些,并且我们常用sprintf和snprintf进行整型到字符串的转换,那么使用过程中怎么去更好的控制格式呢?它们又分别是什么含义呢?今天这篇文章带你一一解答</p>
<p>总体格式:</p>
<figure class="highlight erlang-repl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">%【参数】【标志】【宽度】【.精度】【长度】类型</span></span><br></pre></td></tr></table></figure>
<h3 id="一、参数"><a href="#一、参数" class="headerlink" title="一、参数"></a>一、参数</h3><p>参数字段为 POSIX 扩展功能,非 C99 标准定义。使用 <code>m$</code> 指定格式化字符串之后的第 m 个参数,从 1 开始编号。假如使用了参数字段,则所有的参数必须都至少使用一次,即从 <code>1$</code> 到 <code>n$</code> 都必须至少出现一次(其中 <code>n</code> 为格式化字符串之后的参数个数),否则编译时将产生如下警告:</p>
<blockquote>
<p>warning: missing $ operand number in format [-Wformat=]</p>
</blockquote>
<p>借助参数字段,可以实现参数的多次使用、乱序使用等,而不需要重复书写参数。例如:<code>printf("%2$d %2$#x; %1$d %1$#x",16,17)</code> 将输出 <code>17 0x11; 16 0x10</code>,两个参数都使用了两次,且先使用第二个参数(同时也使用了下一节的 <code>#</code> 标志)。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%2$d %2$x, %1$i %1$#x\n"</span>, <span class="number">12</span>, <span class="string">'c'</span>); <span class="comment">//2$ 1$为参数,x指定为16进制输出,d指定为10进制输出,#在16进制输出时添加0x</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//result is: 99 63, 12 0xc</span></span><br></pre></td></tr></table></figure>
<h3 id="二、标示"><a href="#二、标示" class="headerlink" title="二、标示"></a>二、标示</h3><ul>
<li>-:左对齐(默认为右对齐)</li>
<li>+:给正数附加符号前缀(默认正数没有任何前缀)</li>
<li>:空格给正数附加空格前缀</li>
<li>0:指定了宽度字段且为右对齐时,前缀补0(默认补空格;当使用了-标志左对齐时,0标志失效)</li>
<li>#: 使用【备选格式】。对于g和G类型,不省略小数点部分最后的0;对于f, F, e, E, g, G类型,总是输出小数点;对于o, x, X类型,分别在非零数值前附加0, 0x, 0X前缀</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"%-d\n"</span>, <span class="number">122422312</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%+i\n"</span>, <span class="number">1224223123</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"% d\n"</span>, <span class="number">1224223123</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%04d\n"</span>, <span class="number">12</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%#f\n"</span>, <span class="number">1.23</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%#o\n"</span>,<span class="number">10</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%#x\n"</span>,<span class="number">10</span>);</span><br></pre></td></tr></table></figure>
<h3 id="三、宽度"><a href="#三、宽度" class="headerlink" title="三、宽度"></a>三、宽度</h3><p>宽度字段指定输出字符的最小长度,长度不足的输出将使用填充字段补齐,填充字符及对齐方式使用上述的0标志和-标志确定</p>
<p>当指定宽度字段时,可使用确定的整数值静态指定,也可使用*号由某个参数动态指定。例如,</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"%0*d\n"</span>, <span class="number">5</span>, <span class="number">10</span>)</span><br></pre></td></tr></table></figure>
<p>将会输出:00010。</p>
<h3 id="四、精度"><a href="#四、精度" class="headerlink" title="四、精度"></a>四、精度</h3><p>精度字段指出输出字符的最大长度。对于浮点型数据来说,精度字段指定了小数点后的最大有效位数;对字符串来说,精度字段指定了输出的最大字符数。</p>
<p>与宽度字段相同,指定精度字段时,也可以使用确定的整数或者*号动态指定。为了与宽度字段做出区分,精度字段前面必须加句点。例如:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"%.*f\n"</span>,<span class="number">3</span>, <span class="number">12.34445</span>)</span><br></pre></td></tr></table></figure>
<p>将会输出:12.344</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">printf</span><span class="params">(<span class="string">"%.*s\n"</span>,<span class="number">3</span>, <span class="string">"abcdefgh"</span>)</span></span></span><br></pre></td></tr></table></figure>
<p>将会输出abc。</p>
<p>如果没有句点,将会解释为宽度标志(最小长度),而精度字段没有指定,因此会输出abcdefgh</p>
<h3 id="五、长度"><a href="#五、长度" class="headerlink" title="五、长度"></a>五、长度</h3><ul>
<li><code>hh</code>: 用于将 <code>char</code> 型参数转换成 <code>int</code> 型输出。</li>
<li><code>h</code>: 用于将 <code>short</code> 型参数转换成 <code>int</code> 型输出。</li>
<li><code>l</code>: 用于输出 <code>long</code> 型参数。对于浮点型无效果。</li>
<li><code>ll</code>: 用于输出 <code>long long</code> 型参数。</li>
<li><code>L</code>: 用于输出 <code>long double</code> 型参数。</li>
<li><code>z</code>: 用于输出 <code>size_t</code> 型参数。</li>
<li><code>j</code>: 用于输出 <code>intmax_t</code> 型参数。</li>
<li><code>t</code>: 用于输出 <code>ptrdiff_t</code> 型参数。</li>
</ul>
<p>另有一些平台特定的非标准长度字符,如 <code>I</code>、<code>I32</code>、<code>I64</code>、<code>q</code> 等</p>
<h3 id="六、类型"><a href="#六、类型" class="headerlink" title="六、类型"></a>六、类型</h3><ul>
<li>%:原样输出一个%符号,此类型不接收任何其他字段,即只能使用%%</li>
<li>d, i: 输出十进制signed int型数据。二者仅仅在使用scanf输入时有区别(使用%i将0x开头的解释为16进制,将0开头的数解释为8进制数)</li>
<li>u:输出十进制unsigned int型数据</li>
<li>f,F:以定点数表示法输出double型数据。二者区别在于无限小数和 NaN 输出时是全小写的 <code>inf</code>、<code>infinity</code>、<code>nan</code> 还是全大写的 <code>INF</code>、<code>INFINITY</code>、<code>NAN</code></li>
<li>e, E: 以指数表示法输出double类型数据。二者区别在于字符e的大小写</li>
<li>g,G:根据指数自动选择定点数表示法还是指数表示法。二者的区别在于输出字符的大小写。以定点数表示法输出时与f/F的区别在于,可能省略小数部分最后的0或小数点(数据为整数时)</li>
<li>x, X: 输出十六进制 <code>unsigned int</code> 型数据。二者区别在于十六进制数的字符大小写</li>
<li>o : 输出八进制 <code>unsigned int</code> 型数据。</li>
<li>s: 输出以\0为结尾的字符串</li>
<li>c:输出一个char字符</li>
<li>p:输出void*,输出格式依赖于具体实现</li>
<li>a,A:输出十六进制double型数据,前缀0x或0X</li>
<li>n : 将当前的格式化字符串中已成功输出的字符数写入一个整型参数,字符数不包括 <code>\n</code>、<code>\t</code> 等转义字符。从输入输出的方向来说,此类型使用时更像是在 <code>scanf</code> 中接受输入,只不过输入不是来自用户、而是来自系统计数。注意:此计数仅对当前格式化字符串有效,重新开始一个格式化字符串时,计数将重置为 0。例如:<code>printf("%n", &num)</code> 将把 <code>num</code> 赋值为 0。</li>
</ul>
<figure class="highlight cc"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"%%\n"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%d, %i\n"</span>, <span class="number">1</span>, <span class="number">-2</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%u\n"</span>, <span class="number">-1</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%f, %F\n"</span>, <span class="number">12.0</span>, <span class="number">13.9</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%e, %E\n"</span>, <span class="number">12.0</span>, <span class="number">18.0</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%g, %G\n"</span>, <span class="number">1212333444.0</span>, <span class="number">123.0</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%x, %X\n"</span>, <span class="number">12</span>, <span class="number">13</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%o\n"</span>, <span class="number">12</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%s\n"</span>, <span class="string">"11111"</span>);</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%c\n"</span>, <span class="string">'a'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">std</span>::<span class="built_in">string</span> str = <span class="string">"jack"</span>;</span><br><span class="line"><span class="keyword">void</span>* s = &str;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%p\n"</span>, s);</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"%a, %A\n"</span>, <span class="number">12.0</span>, <span class="number">12.87</span>);</span><br><span class="line"><span class="comment">// printf("%f\n", 12.0);</span></span><br></pre></td></tr></table></figure>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
<h3 class="article-read"><a href="/2020/05/17/printf、sprinf即snprinf的格式化的使用/"><span>more</span></a></h3>
</article>
<article class="article-container ">
<h3 class="article-title"><a href="/2020/05/17/c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比/"><span>c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2020/05/17/c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比/" rel="bookmark">
<time class="entry-date published" datetime="2020-05-17T06:29:54.392Z">
2020-05-17
</time>
</a>
</span>
<br />
</div>
<div class="article-content">
<div class="entry">
<h1 id="c-中sprintf-、-snprintf、-、-、append拼接字符串效率对比"><a href="#c-中sprintf-、-snprintf、-、-、append拼接字符串效率对比" class="headerlink" title="c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比"></a>c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比</h1><p>c++中常用的字符串拼接有snprintf 、append、+,以及+=,众所周知,使用sprintf容易造成内存溢出的问题,所以这里暂时不针对它进行分析比较。那么其他几个字符串拼接函数中,哪个函数的效率是最高的呢?让我们用代码来实验一下。</p>
<h2 id="一、使用snprintf、-、-、-append进行实验"><a href="#一、使用snprintf、-、-、-append进行实验" class="headerlink" title="一、使用snprintf、+=、 +、 append进行实验"></a>一、使用snprintf、+=、 +、 append进行实验</h2><p>代码如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><chrono></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><map></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/time.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="built_in">std</span>::<span class="built_in">string</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> milliseconds_double = <span class="built_in">std</span>::chrono::duration<<span class="keyword">double</span> , <span class="built_in">std</span>::milli>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TimeCount</span></span></span><br><span class="line"><span class="class">{</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> TimeCount()</span><br><span class="line"> {</span><br><span class="line"> start = <span class="built_in">std</span>::chrono::system_clock::now();</span><br><span class="line"> }</span><br><span class="line"> ~TimeCount() = <span class="keyword">default</span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">double</span> <span class="title">get</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="built_in">end</span> = <span class="built_in">std</span>::chrono::system_clock::now();</span><br><span class="line"> <span class="keyword">auto</span> dura = <span class="built_in">std</span>::chrono::duration_cast<milliseconds_double>(<span class="built_in">end</span> - start);</span><br><span class="line"> <span class="keyword">return</span> dura.count();</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">reset</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> start = <span class="built_in">std</span>::chrono::system_clock::now();</span><br><span class="line"> }</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="built_in">std</span>::chrono::system_clock::time_point start;</span><br><span class="line"> <span class="built_in">std</span>::chrono::system_clock::time_point <span class="built_in">end</span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">appendTest</span><span class="params">(<span class="keyword">int</span> repeatTime, <span class="built_in">string</span>& str)</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">string</span> <span class="title">tempStr</span><span class="params">(<span class="string">"just a test"</span>)</span></span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>; i < repeatTime; i++){</span><br><span class="line"> str.append(tempStr);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">plusTest</span><span class="params">(<span class="keyword">int</span> repeatTime, <span class="built_in">string</span>& str)</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">string</span> <span class="title">tempStr</span><span class="params">(<span class="string">"just a test"</span>)</span></span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>; i < repeatTime; i++){</span><br><span class="line"> str = str + tempStr;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">plusAndEqualTest</span><span class="params">(<span class="keyword">int</span> repeatTime, <span class="built_in">string</span>& str)</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">string</span> <span class="title">tempStr</span><span class="params">(<span class="string">"just a test"</span>)</span></span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>; i < repeatTime; i++){</span><br><span class="line"> str += tempStr;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">snPrintfTest</span><span class="params">(<span class="keyword">int</span> repeatTime, <span class="built_in">string</span>& str)</span></span>{</span><br><span class="line"> <span class="function"><span class="built_in">string</span> <span class="title">tempStr</span><span class="params">(<span class="string">"just a test"</span>)</span></span>;</span><br><span class="line"> <span class="keyword">size_t</span> LEN = tempStr.<span class="built_in">size</span>() * repeatTime;</span><br><span class="line"> <span class="keyword">char</span> buff[LEN+<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">char</span> *tempBuff = buff;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i =<span class="number">0</span>; i < repeatTime; i++){</span><br><span class="line"> <span class="built_in">snprintf</span>(tempBuff, LEN+<span class="number">1</span>, <span class="string">"%s"</span>, tempStr.c_str());</span><br><span class="line"> tempBuff += tempStr.<span class="built_in">size</span>();</span><br><span class="line"> }</span><br><span class="line"> str = <span class="built_in">string</span>(buff);</span><br><span class="line">}</span><br><span class="line"></span><br><span 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>{</span><br><span class="line"> <span class="keyword">size_t</span> REPEAT = <span class="number">300</span>;</span><br><span class="line"> <span class="keyword">if</span>(argc == <span class="number">2</span>){</span><br><span class="line"> REPEAT = <span class="built_in">std</span>::atoi(argv[<span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> TimeCount t1;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span> strAppend;</span><br><span class="line"> appendTest(REPEAT, strAppend);</span><br><span class="line"> <span class="keyword">double</span> appendCost = t1.<span class="built_in">get</span>();</span><br><span class="line"> t1.reset();</span><br><span class="line"></span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span> strplus;</span><br><span class="line"> plusTest(REPEAT, strplus);</span><br><span class="line"> <span class="keyword">double</span> plusCost = t1.<span class="built_in">get</span>();</span><br><span class="line"> t1.reset();</span><br><span class="line"></span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span> strplusAndEqual;</span><br><span class="line"> plusAndEqualTest(REPEAT, strplusAndEqual);</span><br><span class="line"> <span class="keyword">double</span> plusEqualCost = t1.<span class="built_in">get</span>();</span><br><span class="line"> t1.reset();</span><br><span class="line"></span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">string</span> strsnPrintf;</span><br><span class="line"> snPrintfTest(REPEAT, strsnPrintf);</span><br><span class="line"> <span class="keyword">double</span> snPrintfCost = t1.<span class="built_in">get</span>();</span><br><span class="line"> t1.reset();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(strAppend == strplus && strplus == strplusAndEqual && strplusAndEqual == strsnPrintf){</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"They all the same "</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"The are different"</span> << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// std::cout << "same :" << strAppend << std::endl;</span></span><br><span class="line"> <span class="comment">// std::cout << "diff :" << strsnPrintf << std::endl;</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"append cost :"</span> << appendCost << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"plus cost :"</span> << plusCost << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"plusequal cost :"</span> << plusEqualCost << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="built_in">std</span>::<span class="built_in">cout</span> << <span class="string">"snprintf cost :"</span> << snPrintfCost << <span class="built_in">std</span>::<span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>通过对比不同拼接函数在连续相同次数的拼接耗时,我们可以初步得出以下结论:</p>
<p><strong><em>“+=” 的性能最佳,其次是append,第三名是snprintf,最差的属于“+”</em></strong></p>
<p>实验结果如下图所示:</p>
<p><img src="D:%5Clocalmd%5C1589694320(1).jpg" alt="1589694320(1)"></p>
<p><img src="D:%5Clocalmd%5C1589694381(1).jpg" alt="1589694381(1)"></p>
<p><img src="D:%5Clocalmd%5C1589694409(1).jpg" alt="1589694409(1)"></p>
<h2 id="二、总结"><a href="#二、总结" class="headerlink" title="二、总结"></a>二、总结</h2><p>为什么会出现上述实验结果,让我们来简单分析一下其中背后的原因,”+=“和append方法效率远远高于”+”,因为”+“在每次拼接后会在内存中创建一个新对象,然后将拼接后的字符串赋值给新对象,频繁的创建对象与拷贝消耗了大量时间。而”+=”和append每次直接在原字符串进行拼接,直到字符串capacity不够时,才重新分配空间(需要一次对象创建和拷贝)。</p>
<p>参考:</p>
<p><a href="https://stackoverflow.com/questions/18892281/most-optimized-way-of-concatenation-in-strings/18892355" target="_blank" rel="noopener">https://stackoverflow.com/questions/18892281/most-optimized-way-of-concatenation-in-strings/18892355</a></p>
<p><a href="https://stackoverflow.com/questions/611263/efficient-string-concatenation-in-c" target="_blank" rel="noopener">https://stackoverflow.com/questions/611263/efficient-string-concatenation-in-c</a></p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
<h3 class="article-read"><a href="/2020/05/17/c++中sprintf 、 snprintf、+= 、+、append拼接字符串效率对比/"><span>more</span></a></h3>
</article>
<article class="article-container ">
<h3 class="article-title"><a href="/2020/05/16/C++中#pargma once与#ifndef的使用/"><span>C++中#pargma once与#ifndef的使用</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2020/05/16/C++中#pargma once与#ifndef的使用/" rel="bookmark">
<time class="entry-date published" datetime="2020-05-16T14:00:37.554Z">
2020-05-16
</time>
</a>
</span>
<br />
</div>
<div class="article-content">
<div class="entry">
<h1 id="C-C-中-pargma-once与-ifndef的使用"><a href="#C-C-中-pargma-once与-ifndef的使用" class="headerlink" title="C/C++中#pargma once与 #ifndef的使用"></a>C/C++中#pargma once与 #ifndef的使用</h1><p>在c/c++中,为了避免同一个文件被include多次,有两种不同的方式解决这个问题:</p>
<h2 id="一、-ifndef方式"><a href="#一、-ifndef方式" class="headerlink" title="一、#ifndef方式"></a>一、#ifndef方式</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> SOME_UNIQUE_NAME_HERE</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SOME_UNIQUE_NAME_HERE</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//some header code here</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br></pre></td></tr></table></figure>
<h2 id="二、-pragma-once方式"><a href="#二、-pragma-once方式" class="headerlink" title="二、#pragma once方式"></a>二、#pragma once方式</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">pragma</span> once </span></span><br><span class="line"></span><br><span class="line"><span class="comment">//some header code here</span></span><br></pre></td></tr></table></figure>
<h2 id="三、两者的比较"><a href="#三、两者的比较" class="headerlink" title="三、两者的比较"></a>三、两者的比较</h2><p> #ifndef的方式是受c/c++语言标准支持。#ifndef方式依赖宏名不能冲突,它不光保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。缺点是如果两个不同的头文件不小心定义了相同的宏名这样会导致想要的头文件没有被包含进去,到时候,头文件明明存在,编译器却说找不到声明的情况。由于编译器每次都需要打开头文件才能判读是否有重复定义,因此在编译大型项目时,#ifndef就会使得编译时间相对较长,因此一些编译器逐渐开始支持#pragma once的方式</p>
<p> #pragma once一般由编译器提供保证:同一个文件不会被两次包含。这里的同一个文件指的是物理上的一个文件,而不是内容相同的两个文件。无法对一个头文件中的一段代码作pragma once声明,而只能针对文件。此方式不会出现宏名不小心一致导致的奇怪问题,大型项目的编译速度也因此提高了一些。缺点是如果某个头文件有多份拷贝,此方法不能保证它们不会被重复包含。</p>
<h2 id="四、总结"><a href="#四、总结" class="headerlink" title="四、总结"></a>四、总结</h2><p> #pragma once方式产生于#ifndef之后。#ifndef 方式受c/c++标准的支持,不受编译器的任何限制;而#pragma once方式有些编译器不支持(如gcc 3.4版本之前不支持#pragma once),兼容性不是很好。#ifndef针对一个文件中的部分代码,而#pragma once只能针对整个文件</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
<h3 class="article-read"><a href="/2020/05/16/C++中#pargma once与#ifndef的使用/"><span>more</span></a></h3>
</article>
<nav class="pagination">
</nav>
</main>
<div class="sidebar
col-lg-3 col-lg-offset-0
col-md-3 col-md-offset-0
col-sm-12
col-xs-12
sidebar-container
">
<div class="sidebar-container">
<div class="search-container">
<form class="site-search-form">
<span class="glyphicon glyphicon-search"></span><input type="text" id="local-search-input" class="st-search-input" placeholder="Search..." />
</form>
<div id="local-search-result" class="local-search-result-cls"></div>
</div>
<script type="text/javascript" id="local.search.active">
var inputArea = document.querySelector("#local-search-input");
inputArea.onclick = function(){ getSearchFile(); this.onclick = null }
inputArea.onkeydown = function(){ if(event.keyCode == 13) return false }
</script>
<div class="categories-container" style="margin-top:40px;">
<p>归档:</p>
</div>
<div class="social-container" style="margin-top:40px;">
<p>Links:</p>
<li class="social-item"><i class="fa fa-fw fa-github"></i><a href="https://github.com/Boseny" target="_blank" rel="noopener">GitHub</a></li>
<li class="social-item"><i class="fa fa-fw fa-weibo"></i><a href="https://weibo.com/boseny" target="_blank" rel="noopener">微博</a></li>
<li class="social-item"><i class=" fa fa-fw zhihu-icon"></i><a href="https://www.zhihu.com/people/boseny" target="_blank" rel="noopener">知乎</a></li>
<li class="social-item"><i class=" fa fa-fw lofter-icon"></i><a href="http://boseny.lofter.com/" target="_blank" rel="noopener">Lofter</a></li>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<p class="site-info">
Proudly powered by <a href="https://hexo.io/" target="_blank">Hexo</a> and
Theme by <a href="https://github.com/BosenY/Lap" target="_blank">Lap</a>
<br/><span id="busuanzi_container_site_uv">
本站访客数<span id="busuanzi_value_site_uv"></span>人次
</span>
</br>
© 2020 whb
</p>
</footer>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-92842840-1', 'auto');
ga('send', 'pageview');
</script>
</div>
</div>
<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://unpkg.com/draw-something/dist/draw.min.js"></script>
<script>
let maxNum = Number.parseInt('10')
let iconText = '❤'
let color = 'red'
new Draw({maxNum, iconText, color})
</script>
<script src="/js/index.js"></script>
<script src="/js/search.js"></script>
</body>
</html>