<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dutor &#187; 边走编程</title>
	<atom:link href="http://www.dutor.net/index.php/category/program/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dutor.net</link>
	<description>大师兄，师傅被妖怪抓走啦！</description>
	<lastBuildDate>Thu, 09 Sep 2010 00:37:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Linux中实现30分钟无操作自动关机</title>
		<link>http://www.dutor.net/index.php/2010/09/linux-auto-halt/</link>
		<comments>http://www.dutor.net/index.php/2010/09/linux-auto-halt/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 23:30:34 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[多线程]]></category>
		<category><![CDATA[守护进程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2418</guid>
		<description><![CDATA[　　<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">上一篇简要介绍了守护进程</a>，现在就来实践一下，写一个自动关机的小程序。该程序可以守护进程的方式运行，当用户在一定时间（比如30分钟）没有鼠标和键盘操作后就会自动关机。
　　这个程序利用了上篇文章中实现的daemonize函数，为程序创建了守护进程所需要的运行环境。
　　由于需要同时监听鼠标和键盘操作，所以需要采用多线程的方式来实现。其中两个线程分别监视鼠标和键盘，一旦检测到相应动作（鼠标点击和移动、击键等），全局时间戳stamp（time_t）就会被设成当前时间。主线程每隔一定时间（比如1秒）检查stamp，若当前时间值（time(NULL)）比stamp大30*60，则执行停机操作（使用system函数执行init 0命令，或者使用reboot函数）。
　　需要说明的是，共享变量stamp需要互斥地访问。另外，对鼠标事件的监听是借助于对设备文件/dev/input/mice的读取（阻塞方式），键盘的监听借助于对/dev/input/event3的非阻塞读取，但我猜想在不同机器上可能会是其它诸如event0,event5之类的文件。
　　不足之处在于，无法对全屏模式进行判断，即是说，如果你全屏看一部较长的电影，可能会被关机……
　　如果你有好的方法来实现本文的功能，还请不吝赐教！]]></description>
			<content:encoded><![CDATA[<p>　　<a href="http://www.dutor.net/index.php/2010/09/daemon-process/" target="_blank">上一篇简要介绍了守护进程</a>，现在就来实践一下，写一个自动关机的小程序。该程序可以守护进程的方式运行，当用户在一定时间（比如30分钟）没有鼠标和键盘操作后就会自动关机。<br />
　　这个程序利用了上篇文章中实现的daemonize函数，为程序创建了守护进程所需要的运行环境。<br />
　　由于需要同时监听鼠标和键盘操作，所以需要采用多线程的方式来实现。其中两个线程分别监视鼠标和键盘，一旦检测到相应动作（鼠标点击和移动、击键等），全局时间戳stamp（time_t）就会被设成当前时间。主线程每隔一定时间（比如1秒）检查stamp，若当前时间值（time(NULL)）比stamp大30*60，则执行停机操作（使用system函数执行init 0命令，或者使用reboot函数）。</p>

<div class="wp_codebox"><table><tr id="p24181"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2418code1"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;unistd.h&gt;</span>
<span style="color: #339933;">#include &lt;sys/types.h&gt;</span>
<span style="color: #339933;">#include &lt;fcntl.h&gt; //~ O_RDWR, S_IRWXU etc.</span>
<span style="color: #339933;">#include &lt;pthread.h&gt;</span>
<span style="color: #339933;">#include &lt;time.h&gt;</span>
<span style="color: #339933;">#include &lt;limits.h&gt;</span>
<span style="color: #339933;">#include &lt;signal.h&gt;</span>
&nbsp;
<span style="color: #993333;">void</span> daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ thread functions</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>listen_ms<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>listen_kb<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ time stamp, keeping the time</span>
<span style="color: #666666; font-style: italic;">//~ when the last KB or Mouse event happened.</span>
<span style="color: #993333;">volatile</span> time_t stamp<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//~ mutex keeping stamp consistent.</span>
pthread_mutex_t stamp_mutex<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//~ initialize the mutex, stamp</span>
    pthread_mutex_init<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
    stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//~ create two threads monitoring the Mouse and Keyboard.</span>
    pthread_t ms_tid<span style="color: #339933;">,</span> kb_tid<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pthread_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>ms_tid<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> listen_ms<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;pthread_create&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>pthread_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>kb_tid<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> listen_kb<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;pthread_create&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> interval <span style="color: #339933;">=</span> <span style="color: #0000dd;">60</span> <span style="color: #339933;">*</span> <span style="color: #0000dd;">30</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> stamp <span style="color: #339933;">&gt;</span> interval <span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #808080; font-style: italic;">/*printf(&quot;shutdown\n&quot;);*/</span>
            <span style="color: #808080; font-style: italic;">/*fflush(stdin);*/</span>
            system<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;init 0&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">//~ join the threads, though it'll never be excuted.</span>
    pthread_join<span style="color: #009900;">&#40;</span>ms_tid<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    pthread_join<span style="color: #009900;">&#40;</span>kb_tid<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
listen_ms<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span> arg<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/input/mice&quot;</span><span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;open mice&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> read<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #808080; font-style: italic;">/*printf(&quot;Moused Moved.\n&quot;);*/</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
        stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
listen_kb<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span> arg<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/input/event3&quot;</span><span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        perror<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;open event3&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">256</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span> read<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #808080; font-style: italic;">/*printf(&quot;Key Hit.\n&quot;);*/</span>
        pthread_mutex_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//time(&amp;stamp);</span>
        stamp <span style="color: #339933;">=</span> time<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        pthread_mutex_unlock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>stamp_mutex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span>
daemonize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    setsid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/null&quot;</span><span style="color: #339933;">,</span> O_RDWR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//int fd = open(&quot;log.txt&quot;, O_RDWR);</span>
    dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    dup2<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    chdir<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    umask<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    signal<span style="color: #009900;">&#40;</span>SIGCHLD<span style="color: #339933;">,</span> SIG_IGN<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　需要说明的是，共享变量stamp需要互斥地访问。另外，对鼠标事件的监听是借助于对设备文件/dev/input/mice的读取（阻塞方式），键盘的监听借助于对/dev/input/event3的非阻塞读取，但我猜想在不同机器上可能会是其它诸如event0,event5之类的文件。<br />
　　不足之处在于，无法对全屏模式进行判断，即是说，如果你全屏看一部较长的电影，可能会被关机……<br />
　　如果你有好的方法来实现本文的功能，还请不吝赐教！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/linux-auto-halt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>守护进程</title>
		<link>http://www.dutor.net/index.php/2010/09/daemon-process/</link>
		<comments>http://www.dutor.net/index.php/2010/09/daemon-process/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 15:29:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[守护进程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2415</guid>
		<description><![CDATA[　　守护进程（daemon process，又称精灵进程），是一种运行在后台，不需要与用户进行交互的程序，其特性与Windows中的<strong>服务</strong>类似。Linux/Unix系统中运行着很多这样的进程，且很多此类进程的进程名都采用name<strong><em>d</em></strong>的形式，比如httpd, vsftpd, inetd等。但这只是一种命名惯例，你完全可以采用其它的命名形式。
<h4>守护进程的特性</h4>
　　守护进程有种种特性，使之成为守护进程。
　　<strong>运行周期较长。</strong>守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动，在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止，守护进程会一直运行（下面会看到守护进程在启动后会脱离执行它的终端）。
　　<strong>脱离其运行环境。</strong>守护进程没有控制终端。进程在创建时（fork）会继承父进程的PCB（进程控制块），因此会同时拥有父进程的许多资源和关系，比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。]]></description>
			<content:encoded><![CDATA[<p>　　守护进程（daemon process，又称精灵进程），是一种运行在后台，不需要与用户进行交互的程序，其特性与Windows中的<strong>服务</strong>类似。Linux/Unix系统中运行着很多这样的进程，且很多此类进程的进程名都采用name<strong><em>d</em></strong>的形式，比如httpd, vsftpd, inetd等。但这只是一种命名惯例，你完全可以采用其它的命名形式。</p>
<h4>守护进程的特性</h4>
<p>　　守护进程有种种特性，使之成为守护进程。<br />
　　<strong>运行周期较长。</strong>守护进程通常在系统启动时由/etc/rc*.d中的启动脚本或者用户在终端手动启动，在系统结束时停止或由用户手动停止。不像普通进程那样在用户退出终端后就被停止，守护进程会一直运行（下面会看到守护进程在启动后会脱离执行它的终端）。<br />
　　<strong>脱离其运行环境。</strong>守护进程没有控制终端。进程在创建时（fork）会继承父进程的PCB（进程控制块），因此会同时拥有父进程的许多资源和关系，比如打开的文件描述符、socket、环境变量、控制终端、进程组、登录会话等。而守护进程需要关闭这些资源、脱离这些关系。</p>
<h4>创建守护进程</h4>
<p>　　鉴于守护进程的这些特性，一个普通进程若想成为守护进程，就需要做一些特殊的操作。</p>
<h5>脱离控制终端</h5>
<p>　　多数用户进程都是从终端运行的，它由与终端关联的shell（用户登录时由login执行的，比如bash程序）经过fork/exec启动。用户程序启动后shell会等待该进程（wait或waitpid等）结束，如果该进程为后台运行，shell会立即返回命令提示符等待用户的其它操作，否则shell会在用户进程结束时才打印命令提示符。<br />
　　所以，为了能使守护进程运行后shell立即返回，通常在程序的入口采用下面的代码来完成：</p>

<div class="wp_codebox"><table><tr id="p24152"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2415code2"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>　　程序fork产生新进程，父进程立即返回（shell等待的就是父进程），shell进程的wait也会成功返回，而子进程则会继续执行。注意，此时子进程的父进程已经过继成为init进程（进程号为1）的子进程了。</p>
<h5>另立门户</h5>
<p>　　执行的上面的操作后，用户进程（子进程）并未真正脱离控制终端。因为子进程继承了父进程的关系，属于父进程所在的进程组，和父进程同属于一个作业，还隶属于控制终端所关联的登录会话（login session）。关于进程组、作业、登录会话等概念，请参考《高级Unix环境编程》(Advanced Programming of Unix Environment)，及Google。<br />
　　若想脱离这些复杂的关系，操作却十分简单，只须在子进程一开始，调用函数setsid()即可。setsid做了以下工作：脱离了原来的进程组和登录会话，创建新的进程组和会话，并担当其进程组的Group Leader和会话的Session Leader.<br />
　　这时候，该进程已经真正脱离了其控制终端，即是说，该进程在其原控制终端退出登录后仍可以在系统中运行。</p>
<h5>关闭继承打开的文件描述符</h5>
<p>　　控制终端，准确说是shell默认打开了三个文件，0代表标准输入，1代表标准输出，2代表标准错误输出。由该shell执行的进程也会继承打开这三个文件，所以它的所有子进程默认的输入和输出也都关联到此终端。因为守护进程也可能有其他用户进程通过exec系列函数执行，守护进程同样会继承这些文件描述符。因此在守护进程中需要关闭继承而来的所有描述符，APUE中stevens的代码：</p>

<div class="wp_codebox"><table><tr id="p24153"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2415code3"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> close_all_fd<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">struct</span> rlimit lim<span style="color: #339933;">;</span>
        <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> i<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>getrlimit<span style="color: #009900;">&#40;</span>RLIMIT_NOFILE<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>lim<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
                <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>lim.<span style="color: #202020;">rlim_cur</span> <span style="color: #339933;">==</span> RLIM_INFINITY<span style="color: #009900;">&#41;</span>
                lim.<span style="color: #202020;">rlim_cur</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">1024</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> lim.<span style="color: #202020;">rlim_cur</span><span style="color: #339933;">;</span> i <span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #339933;">#ifdef MYPERF</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
                        <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#endif</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>close<span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> errno <span style="color: #339933;">!=</span> EBADF<span style="color: #009900;">&#41;</span>
                        <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h5>改变当前工作目录</h5>
<p>　　每个进程都有自己的当前工作目录，进程创建时默认继承父进程的工作目录。守护进程需要将当前工作目录改变，否则其所在目录所挂载的文件系统将无法卸载（可能是你不想要的），通常将其改变之根目录，方法是chdir(&#8220;/&#8221;);</p>
<h5>重设文件创建掩码</h5>
<p>　　为了能够自主控制文件创建权限位，常将文件创建掩码重设为0000，即umask(0);</p>
<h5>忽略SIGCHLD信号</h5>
<p>　　由于守护进程运行周期长，为了避免因为等待子进程而产生僵尸进程，通常需要忽略SIGCHLD信号：signal(SIGCHLD, SIG_IGN);</p>
<h4>总结</h4>
<p>　　方便起见，通常把创建守护进程的一系列操作包装为一个函数，在需要的地方调用即可：</p>

<div class="wp_codebox"><table><tr id="p24154"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2415code4"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ other operations here.</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span>
daemonize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
        <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    setsid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ im so lazy a guy.</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    close<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ you can use I/O functions, but to/from the black hole...</span>
    <span style="color: #0000ff;">int</span> fd <span style="color: #000080;">=</span> open<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;/dev/null&quot;</span>, O_RDWR<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    dup2<span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    dup2<span style="color: #008000;">&#40;</span>fd, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    chdir<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;/&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    umask<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">signal</span><span style="color: #008000;">&#40;</span>SIGCHLD, <span style="color: #0000ff;">SIG_IGN</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/daemon-process/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>共享变量的一个小问题</title>
		<link>http://www.dutor.net/index.php/2010/09/volatile-share-var/</link>
		<comments>http://www.dutor.net/index.php/2010/09/volatile-share-var/#comments</comments>
		<pubDate>Sat, 04 Sep 2010 09:49:36 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[边走编程]]></category>
		<category><![CDATA[volatile]]></category>
		<category><![CDATA[多线程]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2412</guid>
		<description><![CDATA[　　正常情况下，在终端编译执行该多线程程序，首先打印n（0），5秒后再次打印n（1），然后该进程正常退出。
　　但，如果使用gcc编译此程序时，使用优化选项（比如-O1），再执行此程序。首先打印n（0），5秒后再次打印n（1），然后呢，然后就死循环啦！
　　为什么呢？看一看汇编代码就知道了，使用gcc -O1 -S命令编译第一段代码，得到的汇编码：
<pre lang="asm" line="1">
main:
    movl    n(%rip), %eax #从内存中取n值至寄存器eax
.L3:
    testl   %eax, %eax # 与测试eax
    je  .L3 # eax为0时跳转至标号L3处
    movl    $0, %eax
    ret
</pre>
　　真相大白了吧，那该怎么办？对，volatile，<a href="http://www.dutor.net/index.php/2010/08/volatile-const/" target="_blank">参看这里</a>。]]></description>
			<content:encoded><![CDATA[<p>　　看一个很简单的C程序：</p>

<div class="wp_codebox"><table><tr id="p24125"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p2412code5"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>n<span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　很明显，这是一个死循环，因为n的值总为0。再看：</p>

<div class="wp_codebox"><table><tr id="p24126"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2412code6"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>foo<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    pthread_t pth_id<span style="color: #339933;">;</span>
    pthread_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>pth_id<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> foo<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>n<span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">;</span>
    pthread_join<span style="color: #009900;">&#40;</span>pth_id<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>foo<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span> arg<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;n: %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    sleep<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #339933;">++</span>n<span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;++n: %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> n<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　这是一个使用pthread库的多线程程序。主线程在以函数foo创建一个线程后，进入while循环。线程函数foo中，首先打印全局变量n的值，沉睡约5秒钟后，修改n，最后再次打印n值，然后该线程退出（等待主线程join）。<br />
　　正常情况下，在终端编译执行该多线程程序，首先打印n（0），5秒后再次打印n（1），然后该进程正常退出。<br />
　　但，如果使用gcc编译此程序时，使用优化选项（比如-O1），再执行此程序。首先打印n（0），5秒后再次打印n（1），然后呢，然后就死循环啦！<br />
　　为什么呢？看一看汇编代码就知道了，使用gcc -O1 -S命令编译第一段代码，得到的汇编码：</p>

<div class="wp_codebox"><table><tr id="p24127"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2412code7"><pre class="asm" style="font-family:monospace;">main<span style="color: #339933;">:</span>
    movl    n<span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span>rip<span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span> #从内存中取n值至寄存器<span style="color: #00007f;">eax</span>
<span style="color: #339933;">.</span>L3<span style="color: #339933;">:</span>
    testl   <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span> # 与测试<span style="color: #00007f;">eax</span>
    <span style="color: #00007f; font-weight: bold;">je</span>  <span style="color: #339933;">.</span>L3 # <span style="color: #00007f;">eax</span>为<span style="color: #0000ff;">0</span>时跳转至标号L3处
    movl    $<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
    <span style="color: #00007f; font-weight: bold;">ret</span></pre></td></tr></table></div>

<p>　　真相大白了吧，那该怎么办？对，volatile，<a href="http://www.dutor.net/index.php/2010/08/volatile-const/" target="_blank">参看这里</a>。<br />
　　所以，在多线程程序中，共享变量除了同步问题外，还要注意编译器的优化和数据的一致性问题。除了多线程程序外，多进程通讯也会有相似的问题，另外，映射到内存的外部端口寄存器变量也需要使用volatile。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/09/volatile-share-var/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>const在C和C++中的区别</title>
		<link>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/</link>
		<comments>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 13:50:48 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[const]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2408</guid>
		<description><![CDATA[　　const在C，尤其是C++，是个老生常谈的问题，但这里不谈const具体有哪些特性，如何使用，而是说说const在C和C++中的区别。编译器，C使用gcc，C++使用g++，其它编译器（cl等）请自行验证。
　　在我的印象中，const就是<strong>常量</strong>（<em>const</em>ant）。但这并不是真的。在C中，const仅仅表示其所修饰对象<strong>不可修改</strong>。常量和所谓“不可修改”有什么区别呢？C中，const int N = 10; 这样的语句声明了一个<strong>整型数据</strong>，声明之后你不能再为其赋值，此即为<strong>不可修改</strong>。但在C中，N却不是常量，而诸如372, 3.72, 'A'之类才是常量，在C中定义常量通常使用#define。而在C++中，const int N = 10; 就会定义N为常量。
　　怎么证明呢？你可能知道，定义静态数组，必须使用整型常量指定其大小，那咱们就用这个特性来验证上面描述的观点。
<pre lang="c" line="1">
int
main(int argc, char **argv)
{
    const int N = 10;
    int a[N] = { 1, 2, 3 };
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　const在C，尤其是C++，是个老生常谈的问题，但这里不谈const具体有哪些特性，如何使用，而是说说const在C和C++中的区别。编译器，C使用gcc，C++使用g++，其它编译器（cl等）请自行验证。<br />
　　在我的印象中，const就是<strong>常量</strong>（<em>const</em>ant）。但这并不是真的。在C中，const仅仅表示其所修饰对象<strong>不可修改</strong>。常量和所谓“不可修改”有什么区别呢？C中，const int N = 10; 这样的语句声明了一个<strong>整型数据</strong>，声明之后你不能再为其赋值，此即为<strong>不可修改</strong>。但在C中，N却不是常量，而诸如372, 3.72, &#8216;A&#8217;之类才是常量，在C中定义常量通常使用#define。而在C++中，const int N = 10; 就会定义N为常量。<br />
　　怎么证明呢？你可能知道，定义静态数组，必须使用整型常量指定其大小，那咱们就用这个特性来验证上面描述的观点。</p>

<div class="wp_codebox"><table><tr id="p24088"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2408code8"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　使用g++编译这个程序，没有问题。但若使用gcc，你会得到如下错误信息</p>
<pre>
main.c: In function ‘main’:
main.c:19: error: variable-sized object may not be initialized
main.c:19: warning: excess elements in array initializer
</pre>
<p>　　<br />
　　但事情并未到此结束，如果你把上面代码中int a[N] = { 1, 2, 3 };的初始化列表去掉，即int a[N]; 然后就也能通过gcc的编译，更有甚者，如果你把const int N = 10;的const去掉：int N = 10; 也能通过gcc的编译！这是gcc所支持的特性，即<strong>动态数组</strong>。但最好不要这样做，因为gcc会为此生成大量代码。例如，这段代码</p>

<div class="wp_codebox"><table><tr id="p24089"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2408code9"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>使用gcc生成的汇编代码：</p>

<div class="wp_codebox"><table><tr id="p240810"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2408code10"><pre class="asm" style="font-family:monospace;">&nbsp;
	<span style="color: #339933;">.</span>file	<span style="color: #7f007f;">&quot;main.c&quot;</span>
	<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>	main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
	leal	<span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	andl	$<span style="color: #339933;">-</span><span style="color: #0000ff;">16</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	pushl	<span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">esi</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebx</span>
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	subl	$<span style="color: #0000ff;">60</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">gs</span><span style="color: #339933;">:</span><span style="color: #0000ff;">20</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span> # 此处略去n行
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	<span style="color: #339933;">-</span><span style="color: #0000ff;">28</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span>
	xorl	<span style="color: #339933;">%</span><span style="color: #00007f;">gs</span><span style="color: #339933;">:</span><span style="color: #0000ff;">20</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span>
	<span style="color: #00007f; font-weight: bold;">je</span>	<span style="color: #339933;">.</span>L3
	<span style="color: #00007f; font-weight: bold;">call</span>	__stack_chk_fail
<span style="color: #339933;">.</span>L3<span style="color: #339933;">:</span>
	leal	<span style="color: #339933;">-</span><span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	addl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebx</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">esi</span>
	popl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	leal	<span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	<span style="color: #00007f; font-weight: bold;">ret</span></pre></td></tr></table></div>

<p>　　整个汇编文件有96行之多。而使用g++（<strong>N为常量</strong>）编译生成的汇编文件只有23行：</p>

<div class="wp_codebox"><table><tr id="p240811"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p2408code11"><pre class="asm" style="font-family:monospace;">	<span style="color: #339933;">.</span>file	<span style="color: #7f007f;">&quot;main.c&quot;</span>
	<span style="color: #339933;">.</span>text
<span style="color: #339933;">.</span>globl main
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">type</span>	main<span style="color: #339933;">,</span> @function
main<span style="color: #339933;">:</span>
<span style="color: #339933;">.</span>LFB0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span>cfi_startproc
	<span style="color: #339933;">.</span>cfi_personality <span style="color: #0000ff;">0x0</span><span style="color: #339933;">,</span>__gxx_personality_v0
	pushl	<span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	<span style="color: #339933;">.</span>cfi_def_cfa_offset <span style="color: #0000ff;">8</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span>
	<span style="color: #339933;">.</span>cfi_offset <span style="color: #0000ff;">5</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">8</span>
	<span style="color: #339933;">.</span>cfi_def_cfa_register <span style="color: #0000ff;">5</span>
	subl	$<span style="color: #0000ff;">48</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">esp</span>
	movl	$<span style="color: #0000ff;">10</span><span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">ebp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
	<span style="color: #339933;">.</span>cfi_endproc
<span style="color: #339933;">.</span>LFE0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span><span style="color: #000000; font-weight: bold;">size</span>	main<span style="color: #339933;">,</span> <span style="color: #339933;">.-</span>main
	<span style="color: #339933;">.</span>ident	<span style="color: #7f007f;">&quot;GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3&quot;</span>
	<span style="color: #339933;">.</span>section	<span style="color: #339933;">.</span>note<span style="color: #339933;">.</span>GNU<span style="color: #339933;">-</span><span style="color: #000000; font-weight: bold;">stack</span><span style="color: #339933;">,</span><span style="color: #7f007f;">&quot;&quot;</span><span style="color: #339933;">,</span>@progbits</pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/08/const-c-cpp-difference/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[C/C++]volatile</title>
		<link>http://www.dutor.net/index.php/2010/08/volatile-const/</link>
		<comments>http://www.dutor.net/index.php/2010/08/volatile-const/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 12:05:25 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[const]]></category>
		<category><![CDATA[volatile]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2387</guid>
		<description><![CDATA[<h4>volatile</h4>
　　可能很多人都没用过<span class="word">C/C++</span>中的这个关键词，甚至不知道它的存在，本人以前也只是有所耳闻，但似懂非懂。
　　这是一个<strong>类型修饰符</strong>，位置同<span class="word">const</span>、<span class="word">static</span>等。一个使用<span class="word">volatile</span>修饰的变量，比如<em><span class="word">volatile int i;</span> </em>每次对该变量的直接引用，都会访问内存，而不是从寄存器中读取（如果其已经在寄存器中）。这样一来，<span class="word">volatile</span>似乎没什么用处，反倒会使数据的读取相对变慢很多。但是，如果没有<span class="word">volatile</span>，编译器可能会优化你的程序，使得数据从寄存器中读取，从而加快程序的运行，但如果这个变量是同其它进程/线程<strong>共享</strong>的，就可能造成数据的不一致。多线程情况下，你可以使用互斥机制来保证对共享数据访问的原子性。但是，在单片机等嵌入式环境中，硬件经常不会有这种<strong>互斥机制</strong>的支持，这时某些共享的数据（比如端口）就可能会产生不一致的情况。而使用<span class="word">volatile</span>就会使编译器不对代码进行优化，每次对该变量的访问都会从内存中读取。
　　下面通过观察使用<span class="word">volatile</span>前后编译产生的汇编代码的不同，来加深对<span class="word">volatile</span>关键词的理解。
<pre lang="asm" line="1">
[ ... ]
main:
[ ... ]
	call	foo # 调用函数foo，返回值保存至寄存器eax
	movl	%eax, 44(%esp) # 为i赋值
	movl	44(%esp), %edx # 读取i值
	movl	44(%esp), %ecx # 读取i值
	movl	44(%esp), %eax # 读取i值
	movl	%ecx, 16(%esp) # 参数k入栈，使用i值
	movl	%edx, 12(%esp) # 参数j入栈，使用i值
	movl	%eax, 8(%esp) # 参数i入栈
	movl	$.LC0, 4(%esp) # 格式字符串地址入栈
	call	__printf_chk
	movl	$0, %eax
	leave
	ret
[ ... ]
</pre>]]></description>
			<content:encoded><![CDATA[<h4>volatile</h4>
<p>　　可能很多人都没用过<span class="word">C/C++</span>中的这个关键词，甚至不知道它的存在，本人以前也只是有所耳闻，但似懂非懂。<br />
　　这是一个<strong>类型修饰符</strong>，位置同<span class="word">const</span>、<span class="word">static</span>等。一个使用<span class="word">volatile</span>修饰的变量，比如<em><span class="word">volatile int i;</span> </em>每次对该变量的直接引用，都会访问内存，而不是从寄存器中读取（如果其已经在寄存器中）。这样一来，<span class="word">volatile</span>似乎没什么用处，反倒会使数据的读取相对变慢很多。但是，如果没有<span class="word">volatile</span>，编译器可能会优化你的程序，使得数据从寄存器中读取，从而加快程序的运行，但如果这个变量是同其它进程/线程<strong>共享</strong>的，就可能造成数据的不一致。多线程情况下，你可以使用互斥机制来保证对共享数据访问的原子性。但是，在单片机等嵌入式环境中，硬件经常不会有这种<strong>互斥机制</strong>的支持，这时某些共享的数据（比如端口）就可能会产生不一致的情况。而使用<span class="word">volatile</span>就会使编译器不对代码进行优化，每次对该变量的访问都会从内存中读取。<br />
　　下面通过观察使用<span class="word">volatile</span>前后编译产生的汇编代码的不同，来加深对<span class="word">volatile</span>关键词的理解。<br />
　　对于下面的<span class="word">C</span>代码：</p>

<div class="wp_codebox"><table><tr id="p238712"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code12"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">int</span> foo<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>i<span style="color: #000040;">++</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">20</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> i<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> k <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d, %d, %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, i, j, k<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　代码中，使用<em>foo()</em>的返回值（20）来初始化整型变量<span class="word">i</span>。之所以不直接赋值，是为了<strong>防止</strong>编译器优化，下面对<span class="word">j,k</span>的赋值将直接使用<span class="word">20</span>，而不是<span class="word">i</span>，也不是寄存器。使用下面的命令编译：</p>

<div class="wp_codebox"><table><tr id="p238713"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2387code13"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-S</span> <span style="color: #660033;">-O1</span> main.c <span style="color: #666666; font-style: italic;"># 优化等级1</span></pre></td></tr></table></div>

<p>　　产生的汇编代码：</p>

<div class="wp_codebox"><table><tr id="p238714"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code14"><pre class="asm" style="font-family:monospace;"><span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
<span style="color: #339933;">.</span>LC0<span style="color: #339933;">:</span>
	<span style="color: #339933;">.</span>string	<span style="color: #7f007f;">&quot;%d, %d, %d\n&quot;</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
main<span style="color: #339933;">:</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	foo # 调用函数foo，返回值保存至寄存器<span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">16</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数k入栈
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数j入栈
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数i入栈
	movl	$<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 格式字符串地址入栈
	movl	$<span style="color: #0000ff;">1</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	__printf_chk
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span></pre></td></tr></table></div>

<p>　　可以看到，对<span class="word">j,k</span>的赋值都是由寄存器<span class="word">eax</span>进行的。下面把代码中的<em><span class="word">int i = foo();</span></em>换成<em><span class="word">volatile int i = foo();</span></em>，编译得到的汇编代码是：</p>

<div class="wp_codebox"><table><tr id="p238715"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2387code15"><pre class="asm" style="font-family:monospace;"><span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
main<span style="color: #339933;">:</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span>
	<span style="color: #00007f; font-weight: bold;">call</span>	foo # 调用函数foo，返回值保存至寄存器<span style="color: #00007f;">eax</span>
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 为i赋值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">edx</span> # 读取i值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span> # 读取i值
	movl	<span style="color: #0000ff;">44</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span> # 读取i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">16</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数k入栈，使用i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">edx</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">12</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数j入栈，使用i值
	movl	<span style="color: #339933;">%</span><span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 参数i入栈
	movl	$<span style="color: #339933;">.</span>LC0<span style="color: #339933;">,</span> <span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#40;</span><span style="color: #339933;">%</span><span style="color: #00007f;">esp</span><span style="color: #009900; font-weight: bold;">&#41;</span> # 格式字符串地址入栈
	<span style="color: #00007f; font-weight: bold;">call</span>	__printf_chk
	movl	$<span style="color: #0000ff;">0</span><span style="color: #339933;">,</span> <span style="color: #339933;">%</span><span style="color: #00007f;">eax</span>
	<span style="color: #00007f; font-weight: bold;">leave</span>
	<span style="color: #00007f; font-weight: bold;">ret</span>
<span style="color: #009900; font-weight: bold;">&#91;</span> <span style="color: #339933;">...</span> <span style="color: #009900; font-weight: bold;">&#93;</span></pre></td></tr></table></div>

<p>　　可以看到，每次对i的访问都是从内存（栈）中读取的。</p>
<h4>volatile vs. const</h4>
<p>　　正像上面所描述的那样，<span class="word">volatile</span>的意思是<strong>“易变的”</strong>。<span class="word">C/C++</span>中还有另外一个关键词叫<span class="word">const</span>，用来限定变量不可被改变。似乎volatile和const意思相反，水火不容。但<span class="word"><em>volatile const int N = 0;</em></span>这样的语句是允许存在的。为什么呢？其实，这个语句可以这样来理解：变量<span class="word">N</span>在本程序（或者设备）中是不可（禁止）改变的，但它可能会被其它程序（或者设备）改变。你或许知道，<span class="word">const</span>只是编译器的限定，而没有执行期的检查，因此<span class="word">const</span>也只是限于单个进程，因此<span class="word">volatile</span>和<span class="word">const</span>这两个关键词并不冲突。<br />
　　另外，普通的整型<span class="word">const</span>变量，比如<em><span class="word">const int N = 10; int a[N];</span></em> 中，变量<span class="word">N</span>可能并不会被分配内存（除非程序里面有显式使用N地址的表达式）。但是，根据<span class="word">volatile</span>变量的特性，<em><span class="word">volatile const int N = 10;</span></em>中变量<span class="word">N</span>是一定会占用内存的。这一点，亦可以通过观察相应的汇编代码来验证。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/08/volatile-const/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>qsort</title>
		<link>http://www.dutor.net/index.php/2010/07/qsort/</link>
		<comments>http://www.dutor.net/index.php/2010/07/qsort/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 12:57:10 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[qsort]]></category>
		<category><![CDATA[排序]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2347</guid>
		<description><![CDATA[　　对qsort需要注意几点：
<ul>
	<li>qsort中第一个参数是待排序数组的开始地址，既然是数组，各元素就是同类型、同大小的对象，且数组是<strong>“一维数组”</strong>（即地址是连续的）；</li>
	<li>qsort用以区分对象的依据是第二和第三个参数，分别表示对象个数和每个对象的大小（字节）；</li>
	<li>qsort并不知道每个对象的类型和结构，排序准则由用户在第四个参数（比较函数）中指出，qsort按该比较函数准则的“升序”对数组进行排序；</li>
	<li>标准C不支持运算符重载，各对象的交换（因为这是qsort）靠的是逐字节的拷贝（memcpy?）。</li>
</ul>
　　在上面的两片代码中，待排序的对象一个是字符型指针，一个是char (*)[10]型数组。然后，就没有然后了。]]></description>
			<content:encoded><![CDATA[<p>　　Felix那里看到的，关于用qsort对指针式字符串数组和二维型字符串数组的排序的，觉得值得贴出来。注意下下面两片代码的区别。</p>

<div class="wp_codebox"><table><tr id="p234716"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2347code16"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>str<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #ff0000;">&quot;xyz&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cdef&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;abcd&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;caaa&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> cmp<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>l<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>r<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>a <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>l<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>b <span style="color: #339933;">=</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">**</span><span style="color: #009900;">&#41;</span>r<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> strcmp<span style="color: #009900;">&#40;</span>a<span style="color: #339933;">,</span> b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    qsort<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #339933;">,</span> N<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> cmp <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> N<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> str<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<div class="wp_codebox"><table><tr id="p234717"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code" id="p2347code17"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> str<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #ff0000;">&quot;xyz&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;cdef&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;abcd&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;caaa&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    qsort<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>str<span style="color: #339933;">,</span> N<span style="color: #339933;">,</span>
            <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">*</span><span style="color: #0000dd;">10</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>strcmp <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> N<span style="color: #339933;">;</span> <span style="color: #339933;">++</span>i<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> str<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　对qsort需要注意几点：</p>
<ul>
<li>qsort中第一个参数是待排序数组的开始地址，既然是数组，各元素就是同类型、同大小的对象，且数组是<strong>“一维数组”</strong>（即地址是连续的）；</li>
<li>qsort用以区分对象的依据是第二和第三个参数，分别表示对象个数和每个对象的大小（字节）；</li>
<li>qsort并不知道每个对象的类型和结构，排序准则由用户在第四个参数（比较函数）中指出，qsort按该比较函数准则的“升序”对数组进行排序；</li>
<li>标准C不支持运算符重载，各对象的交换（因为这是qsort）靠的是逐字节的拷贝（memcpy?）。</li>
</ul>
<p>　　在上面的两片代码中，待排序的对象一个是字符型指针，一个是char (*)[10]型数组。然后，就没有然后了。<br />
　　<br />
　　然后，上面代码，gcc编译出错，g++却可以。<br />
　　const int N = 4; char *str[N];可以。<br />
　　const int N = 4; char *str[N] = {&#8220;a&#8221;,&#8221;b&#8221;,&#8221;c&#8221;,&#8221;d&#8221;};却不可，何解？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/qsort/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Unix/Linux环境下创建和使用静/动态库</title>
		<link>http://www.dutor.net/index.php/2010/07/dynamic-static-library/</link>
		<comments>http://www.dutor.net/index.php/2010/07/dynamic-static-library/#comments</comments>
		<pubDate>Sun, 04 Jul 2010 14:23:55 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[OS基础]]></category>
		<category><![CDATA[动态链接]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2340</guid>
		<description><![CDATA[<h4>动态链接库</h4>
　　动态库和静态库相似，也是各个目标文件的集合。但相比静态链接的程序，动态链接可执行程序要小得多：这类程序运行时需要外部共享 函数库的支持，因此好像并不完整。除了程序体小之外，动态链接允许程序包指定必须的库，而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库，这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因，当前多数程序采用动态链接技术。
　　在Linux中的扩展名通常为.so。但在链接时，并不会被链接到可执行文件中，而是在执行时（需要时）由操作系统的动态加载模块动态地加载到内存，并链接到可执行文件地址空间的相应位置。
　　动态链接库的创建也分为编译和"归档"两个阶段，但不同的是在这两个阶段需要使用一些不同的命令选项。首先，需要将源文件编译成一种成为位置无关码（PIC: Position Independent Code）的目标文件，这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位，关于这种格式可以参考《链接器与加载器》和《程序员的自我修养--链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可，即gcc。还是上面的源文件，执行以下命令：
<pre lang="bash" line="1">
$ cc -c -fpic plus.c sub.c
$ cc -shared -o libmath.so *.o
</pre>]]></description>
			<content:encoded><![CDATA[<h4>库的作用</h4>
<p>　　大体上库的存在，有两方面的原因，一是代码的复用，二是声明和实现的分离。将功能相近的使用模块封装成库，使代码的复用、管理和分发变得简单了许多，例如著名的开源图形库ncurses，你可以自行编译，更可以直接使用已经编译好的现成的库文件。另外，由于库是二进制文件，某种意义上讲，将功能的实现部分隐藏了起来，这就为商业代码的保护提供了一种方式。<br />
　　库文件按照链接方式和时机，可以分为动态库和静态库，下面分别介绍它们在Linux环境中的创建和使用方法。</p>
<h4>静态链接库</h4>
<p>　　静态库是指在程序的链接阶段，其中被用到的代码会被直接链接到可执行文件中的库。静态链接的可执行程序包含了其所需的全部库函数：所有库函数都连接到程序中。 这类程序是完整的，其运行不需要外部库的支持。 静态链接程序的优点之一是其安装之前不需要做环境准备工作 。<br />
　　Linux中，静态库的扩展名通常为.a，它仅仅是一些目标文件（.o）的归档（archive）或者说打包，另外，为了链接时能够快速地定位其中的符号（函数、变量名等），静态库还会包含一个对其中符号的索引。<br />
　　创建静态库的过程十分简单，除编译所必须的工具之外，要用到的命令只有两个ar和ranlib。ar可以将各个目标文件进行归档，ranlib对ar生成的归档文件（即静态库文件）进行索引。假设现在有这样几个源文件：plus.c, sub.c及相应的头文件，另外还有一个用来调用库文件中函数的主文件main.c，它们的内容分别是：<br />
plus.c,</p>

<div class="wp_codebox"><table><tr id="p234018"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2340code18"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
plus<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> a, <span style="color: #0000ff;">int</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000040;">+</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>sub.c,</p>

<div class="wp_codebox"><table><tr id="p234019"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2340code19"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;sub.h&quot;</span>
<span style="color: #0000ff;">int</span>
sub<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> a, <span style="color: #0000ff;">int</span> b<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000040;">-</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>main.c,</p>

<div class="wp_codebox"><table><tr id="p234020"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code" id="p2340code20"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
<span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> plus<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　下面将plus.c和sub.c编译，制作成静态库libmath.a，依次执行：</p>

<div class="wp_codebox"><table><tr id="p234021"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code21"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> plus.c sub.c
$ <span style="color: #c20cb9; font-weight: bold;">ar</span> rc libmath.a plus.o sub.o
$ ranlib libmath.a</pre></td></tr></table></div>

<p>　　现在我们的libmath.a静态库已经制作完成，其中使用了ar命令的两个选项，c表示若库文件不存在则创建之，r表示库文件中若已经存在某个目标文件，且较旧，则执行替换。使用这个静态库更加简单：</p>

<div class="wp_codebox"><table><tr id="p234022"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code22"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c -L. <span style="color: #660033;">-lmath</span> <span style="color: #660033;">-o</span> main
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<h4>动态链接库</h4>
<p>　　动态库和静态库相似，也是各个目标文件的集合。但相比静态链接的程序，动态链接可执行程序要小得多：这类程序运行时需要外部共享 函数库的支持，因此好像并不完整。除了程序体小之外，动态链接允许程序包指定必须的库，而不必将库装入程序包内。动态链接技术还允许多个运行中的程序共享一个库，这样就不会出现同一代码的多份拷贝共占内存的情况了。由于这些原因，当前多数程序采用动态链接技术。<br />
　　在Linux中的扩展名通常为.so。但在链接时，并不会被链接到可执行文件中，而是在执行时（需要时）由操作系统的动态加载模块动态地加载到内存，并链接到可执行文件地址空间的相应位置。<br />
　　动态链接库的创建也分为编译和&#8221;归档&#8221;两个阶段，但不同的是在这两个阶段需要使用一些不同的命令选项。首先，需要将源文件编译成一种成为位置无关码（PIC: Position Independent Code）的目标文件，这种代码可以被加入到内存的任何位置却不需要加载器对其进行重定位，关于这种格式可以参考《链接器与加载器》和《程序员的自我修养&#8211;链接装载与库》中较为详尽的描述。接下来需要将这些位置无关码“归档”为.so文件。整个过程只需一个工具即可，即gcc。还是上面的源文件，执行以下命令：</p>

<div class="wp_codebox"><table><tr id="p234023"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p2340code23"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> <span style="color: #660033;">-fpic</span> plus.c sub.c
$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-shared</span> <span style="color: #660033;">-o</span> libmath.so <span style="color: #000000; font-weight: bold;">*</span>.o</pre></td></tr></table></div>

<p>　　这样，包含plus.o和sub.o的动态库文件libmath.so就创建完成了。其中cc（gcc的符号链接）命令的-fpic或-fPIC选项使之创建位置无关的目标文件，使用-shared选项可以创建最终的动态库文件。<br />
　　使用动态库文件有两种方法，一种是让操作系统的动态加载模块（如ld-linux.so.2）在执行时加载动态库。另一种是在代码中使用dl库动态加载库文件。<br />
　　先介绍下第一种方法。使用这种方法需要在编译可执行文件时指明库名及其路径（对于自己的编写的动态库而言）：</p>

<div class="wp_codebox"><table><tr id="p234024"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p2340code24"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c -L. <span style="color: #660033;">-lmath</span> <span style="color: #660033;">-o</span> main</pre></td></tr></table></div>

<p>　　这时可执行文件main就被创建了，上面的命令并没有将libmath.so中相应的目标代码链接到main中（你可以对比一下这里的main和静态链接的main的大小），只是在库中查找和确认main.c中用到的符号而已。但通常这个main现在还无法正常执行，这涉及到系统查找动态库的路径问题，系统通常只在某些指定的目录（标准路径）下查找所需的库文件，若在标准路径中无法找到所需的库，则会到环境变量LD_LIBRARY_PATH（如果存在的话）指定的目录下查找，若仍无法找到就会报错。因为libmath.so在main的当前目录中，而当前目录通常并不在标准路径之列。为了使libmath.so能够被找到和加载，你可以把它放到标准路径中，但更好的方法是将其所在目录加入到LD_LIBRARY_PATH变量中。执行下面的命令：</p>

<div class="wp_codebox"><table><tr id="p234025"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2340code25"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">LD_LIBRARY_PATH</span>=<span style="color: #007800;">$LD_LIBRARY_PATH</span>:. <span style="color: #666666; font-style: italic;"># 添加当前目录</span>
$ <span style="color: #7a0874; font-weight: bold;">export</span> LD_LIBRARY_PATH <span style="color: #666666; font-style: italic;"># 将环境变量导出，使其在子shell中可用</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<p>　　<br />
　　下面介绍使用dl库加载动态库，dl库中函数很少很简练，看main.c代码:</p>

<div class="wp_codebox"><table><tr id="p234026"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2340code26"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;stdio.h&gt;</span>
<span style="color: #339900;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339900;">#include &lt;unistd.h&gt;</span>
<span style="color: #339900;">#include &lt;dlfcn.h&gt;</span>
<span style="color: #339900;">#include &quot;plus.h&quot;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span> lib_handle <span style="color: #000080;">=</span> dlopen<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./libmath.so&quot;</span>, RTLD_LAZY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>lib_handle<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>plus_ptr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span>, <span style="color: #0000ff;">int</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> dlsym<span style="color: #008000;">&#40;</span>lib_handle, <span style="color: #FF0000;">&quot;plus&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>plus_ptr<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> a <span style="color: #000080;">=</span> plus_ptr<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, <span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        dlclose<span style="color: #008000;">&#40;</span>lib_handle<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　main.c中，首先使用dlopen打开需要的动态库，其中参数RTLD_LAZY指明仅当需要调用该库时才进行加载。dlopen返回一个句柄，dlsym使用该句柄和符号来取得相应函数的地址，这里使用int (*)(int, int)函数指针来接收plus函数的地址。接下来使用得到的函数指针调用相应的函数，最后通过dlclose函数来关闭句柄。编译这个程序需要使用dl动态链接库，因此需要使用gcc的-ldl选项：</p>

<div class="wp_codebox"><table><tr id="p234027"><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code" id="p2340code27"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cc</span> main.c <span style="color: #660033;">-ldl</span> <span style="color: #660033;">-o</span> main
$ .<span style="color: #000000; font-weight: bold;">/</span>main
<span style="color: #000000;">3</span></pre></td></tr></table></div>

<h4>.so与.a文件的对比</h4>
<p>　　最后附上libmath.a和libmath.so文件的内容，使用objdump的-d选项查看的：<br />
libmath.a,</p>
<pre>
In archive libmath.a:

plus.o:     file format elf32-i386
Disassembly of section .text:
00000000 &lt;plus>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	8d 04 02             	lea    (%edx,%eax,1),%eax
   c:	5d                   	pop    %ebp
   d:	c3                   	ret    

sub.o:     file format elf32-i386
Disassembly of section .text:
00000000 &lt;sub>:
   0:	55                   	push   %ebp
   1:	89 e5                	mov    %esp,%ebp
   3:	8b 45 0c             	mov    0xc(%ebp),%eax
   6:	8b 55 08             	mov    0x8(%ebp),%edx
   9:	89 d1                	mov    %edx,%ecx
   b:	29 c1                	sub    %eax,%ecx
   d:	89 c8                	mov    %ecx,%eax
   f:	5d                   	pop    %ebp
  10:	c3                   	ret
</pre>
<p>libmath.so:</p>
<pre>
libmath.so:     file format elf32-i386
Disassembly of section .init:
00000324 &lt;_init>:
 324:	55                   	push   %ebp
 325:	89 e5                	mov    %esp,%ebp
 327:	53                   	push   %ebx
 328:	83 ec 04             	sub    $0x4,%esp
......
0000044c &lt;plus>:
 44c:	55                   	push   %ebp
 44d:	89 e5                	mov    %esp,%ebp
 44f:	8b 45 0c             	mov    0xc(%ebp),%eax
 452:	8b 55 08             	mov    0x8(%ebp),%edx
 455:	8d 04 02             	lea    (%edx,%eax,1),%eax
 458:	5d                   	pop    %ebp
 459:	c3                   	ret
 45a:	90                   	nop
 45b:	90                   	nop

0000045c &lt;sub>:
 45c:	55                   	push   %ebp
 45d:	89 e5                	mov    %esp,%ebp
 45f:	8b 45 0c             	mov    0xc(%ebp),%eax
 462:	8b 55 08             	mov    0x8(%ebp),%edx
 465:	89 d1                	mov    %edx,%ecx
 467:	29 c1                	sub    %eax,%ecx
 469:	89 c8                	mov    %ecx,%eax
 46b:	5d                   	pop    %ebp
 46c:	c3                   	ret
 46d:	90                   	nop
 46e:	90                   	nop
 46f:	90                   	nop
......

Disassembly of section .fini:

000004a8 &lt;_fini>:
 4a8:	55                   	push   %ebp
 4a9:	89 e5                	mov    %esp,%ebp
 4ab:	53                   	push   %ebx
 4ac:	83 ec 04             	sub    $0x4,%esp
 4af:	e8 00 00 00 00       	call   4b4 &lt;_fini+0xc>
 4b4:	5b                   	pop    %ebx
 4b5:	81 c3 40 1b 00 00    	add    $0x1b40,%ebx
 4bb:	e8 d0 fe ff ff       	call   390 &lt;__do_global_dtors_aux>
 4c0:	59                   	pop    %ecx
 4c1:	5b                   	pop    %ebx
 4c2:	c9                   	leave
 4c3:	c3                   	ret
</pre>
<p>　　可见，相对.a，.so有很多额外的代码段，其中比较重要的是<_init>段和<_fini>段。它们分别进行一些前期和后期处理工作，例如<_init>通常在dlopen返回之前执行一些.so库中的一些初始化工作（C++中就可能是全局构造或者静态对象的构造函数）。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/07/dynamic-static-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>struct/class关键字何时是必须的？</title>
		<link>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/</link>
		<comments>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/#comments</comments>
		<pubDate>Fri, 21 May 2010 13:16:54 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2288</guid>
		<description><![CDATA[　　在形如struct structName varName;的语句中，struct是必须的吗？这是一个显而易见的语法问题，但却容易被忽略，尤其容易被C+C++的同志们忽略。
　　在标准C中，struct关键字是必须的：
<pre lang="c" line="1">
struct structName {
    int n;
};
//~ typedef struct structName structName;
int
main()
{
    struct structName n;
    return 0;
}
</pre>
若没有前置的struct关键字，上面的代码就不能通过编译。我的gcc会提示"structName" undeclared, parse error before 'n'的错误。为了方便，通常会使用typedef struct structName structName;语句来为struct structName定义类型别名。
　　但是，在C++中，一般情况下，struct/class关键字就不是必须的。但是，在有些情况下struct/class关键字又是必须的，因为这时的名字structName有歧义性。这是因为，C/C++语言允许用户自定义类型和函数同名。]]></description>
			<content:encoded><![CDATA[<p>　　在形如struct structName varName;的语句中，struct是必须的吗？这是一个显而易见的语法问题，但却容易被忽略，尤其容易被C+C++的同志们忽略。<br />
　　在标准C中，struct关键字是必须的：</p>

<div class="wp_codebox"><table><tr id="p228828"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2288code28"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> structName <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> n<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//~ typedef struct structName structName;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> structName n<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>若没有前置的struct关键字，上面的代码就不能通过编译。我的gcc会提示&#8221;structName&#8221; undeclared, parse error before &#8216;n&#8217;的错误。为了方便，通常会使用typedef struct structName structName;语句来为struct structName定义类型别名。<br />
　　但是，在C++中，一般情况下，struct/class关键字就不是必须的。但是，在有些情况下struct/class关键字又是必须的，因为这时的名字structName有歧义性。这是因为，C/C++语言允许用户自定义类型和函数同名。</p>

<div class="wp_codebox"><table><tr id="p228829"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p2288code29"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> structName <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> n<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> structName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    structName n<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>上面代码，无论使用gcc还是g++，都不能通过编译，即使structName n;明显只能是一个变量定义语句。这时，就需要明确使用关键字struct，即struct structName n;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/is-struct-class-necessary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[STL]容器适配器没有clear()</title>
		<link>http://www.dutor.net/index.php/2010/05/stl-adapter-none-clear/</link>
		<comments>http://www.dutor.net/index.php/2010/05/stl-adapter-none-clear/#comments</comments>
		<pubDate>Tue, 18 May 2010 01:44:01 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[边走编程]]></category>
		<category><![CDATA[STL]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2285</guid>
		<description><![CDATA[　　听XiaFei同学讲课，得知queque&#60;T>没有clear()成员函数，甚觉诧异，察知确凿。非但queue，其它容器适配器，如stack, priority_queque之流，亦无此clear，于此谨记。]]></description>
			<content:encoded><![CDATA[<p>　　听XiaFei同学讲课，得知queque&lt;T>没有clear()成员函数，甚觉诧异，察知确凿。非但queue，其它容器适配器，如stack, priority_queque之流，亦无此clear，于此谨记。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/stl-adapter-none-clear/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>单源最短路径Bellman-Ford算法</title>
		<link>http://www.dutor.net/index.php/2010/05/shortest-path-bellman-ford/</link>
		<comments>http://www.dutor.net/index.php/2010/05/shortest-path-bellman-ford/#comments</comments>
		<pubDate>Thu, 06 May 2010 12:57:48 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[图论]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2254</guid>
		<description><![CDATA[<h4>Bellman-Ford算法简述</h4>
　　<a href="http://www.dutor.net/index.php/2010/04/shortest-path-dijkstra/" target="_blank">Dijkstra算法</a>是处理单源最短路径的有效算法，但它局限于边的权值非负的情况，若图中出现权值为负的边，Dijkstra算法就会失效，求出的最短路径就可能是错的。这时候，就需要使用其他的算法来求解最短路径，Bellman-Ford算法就是其中最常用的一个。该算法由美国数学家理查德•贝尔曼（Richard Bellman, 动态规划的提出者）和小莱斯特•福特（Lester Ford）发明。Bellman-Ford算法的流程如下：
　　给定图G(V, E)（其中V、E分别为图G的顶点集与边集），源点s，
<ol>
	<li>数组Distant[i]记录从源点s到顶点i的路径长度，初始化数组Distant[n]为$$\color{red} \infty$$, Distant[s]为0；</li>
	<li>以下操作循环执行至多n-1次，n为顶点数：
<ul>
	<li>对于每一条边e(u, v)，如果Distant[u] + w(u, v) < Distant[v]，则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值；</li>
	<li>若上述操作没有对Distant进行更新，说明最短路径已经查找完毕，或者部分点不可达，跳出循环。否则执行下次循环；</li>
</ul>
</li>
	<li>为了检测图中是否存在负环路，即权值之和小于0的环路。对于每一条边e(u, v)，如果存在Distant[u] + w(u, v) < Distant[v]的边，则图中存在负环路，即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。</li>
</ol>
　　可知，Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).]]></description>
			<content:encoded><![CDATA[<h4>Bellman-Ford算法简述</h4>
<p>　　<a href="http://www.dutor.net/index.php/2010/04/shortest-path-dijkstra/" target="_blank">Dijkstra算法</a>是处理单源最短路径的有效算法，但它局限于边的权值非负的情况，若图中出现权值为负的边，Dijkstra算法就会失效，求出的最短路径就可能是错的。这时候，就需要使用其他的算法来求解最短路径，Bellman-Ford算法就是其中最常用的一个。该算法由美国数学家理查德•贝尔曼（Richard Bellman, 动态规划的提出者）和小莱斯特•福特（Lester Ford）发明。Bellman-Ford算法的流程如下：<br />
　　给定图G(V, E)（其中V、E分别为图G的顶点集与边集），源点s，</p>
<ol>
<li>数组Distant[i]记录从源点s到顶点i的路径长度，初始化数组Distant[n]为<img src="http://www.dutor.net/wp-content/cache/3a39ec3839566b7a0da75d0b72c48d19.png" align="absmiddle" class="tex" alt="\color{red} \infty" />, Distant[s]为0；</li>
<li>以下操作循环执行至多n-1次，n为顶点数：
<ul>
<li>对于每一条边e(u, v)，如果Distant[u] + w(u, v) < Distant[v]，则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值；</li>
<li>若上述操作没有对Distant进行更新，说明最短路径已经查找完毕，或者部分点不可达，跳出循环。否则执行下次循环；</li>
</ul>
</li>
<li>为了检测图中是否存在负环路，即权值之和小于0的环路。对于每一条边e(u, v)，如果存在Distant[u] + w(u, v) < Distant[v]的边，则图中存在负环路，即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。</li>
</ol>
<p>　　可知，Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).</p>
<h4>Bellman-Ford算法C++实现</h4>

<div class="wp_codebox"><table><tr id="p225430"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2254code30"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> MAXINT <span style="color: #000080;">=</span> <span style="color: #208080;">0xFFFF</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 不可达的路径长度上限</span>
<span style="color: #0000ff;">struct</span> Node
<span style="color: #008000;">&#123;</span>
    Node<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> w<span style="color: #008000;">&#40;</span>MAXINT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> src, <span style="color: #666666;">//~ 最短路径上的上一个顶点</span>
        w<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 到该节点的路径长度</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">struct</span> Edge
<span style="color: #008000;">&#123;</span>
    Edge<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    Edge<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> f, <span style="color: #0000ff;">int</span> t<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> from<span style="color: #008000;">&#40;</span>f<span style="color: #008000;">&#41;</span>, to<span style="color: #008000;">&#40;</span>t<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> from,
        to<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> Adj<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> n, <span style="color: #666666;">// 顶点数</span>
        m, <span style="color: #666666;">//~ 边数</span>
        from,
        to,
        w,
        start<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 源点</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>n<span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span>Node<span style="color: #000080;">&gt;</span> Dist<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> n<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        Adj.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>n, MAXINT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Adj<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>m<span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span>Edge<span style="color: #000080;">&gt;</span> Edges<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> m<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>from<span style="color: #000080;">&gt;&gt;</span>to<span style="color: #000080;">&gt;&gt;</span>w<span style="color: #008080;">;</span>
        Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> w<span style="color: #008080;">;</span>
        Edges.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>Edge<span style="color: #008000;">&#40;</span>from, to<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>start<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 从顶点start开始的最短路径</span>
    Dist<span style="color: #008000;">&#91;</span>start<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~</span>
    <span style="color: #0000ff;">bool</span> flag <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> n <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> j <span style="color: #000080;">&lt;</span> Edges.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>j<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            from <span style="color: #000080;">=</span> Edges<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">from</span><span style="color: #008080;">;</span>
            to <span style="color: #000080;">=</span> Edges<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">to</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dist<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">==</span> MAXINT <span style="color: #000040;">||</span> Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">==</span> MAXINT<span style="color: #008000;">&#41;</span>
                <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dist<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000040;">+</span> Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">&lt;</span> Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">=</span> Dist<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000040;">+</span> Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
                Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">src</span> <span style="color: #000080;">=</span> from<span style="color: #008080;">;</span>
                flag <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>flag <span style="color: #000080;">==</span> <span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">else</span>
            flag <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #666666;">//~ 检测有无负环路</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> j <span style="color: #000080;">&lt;</span> Edges.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>j<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        from <span style="color: #000080;">=</span> Edges<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">from</span><span style="color: #008080;">;</span>
        to <span style="color: #000080;">=</span> Edges<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">to</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dist<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">==</span> MAXINT <span style="color: #000040;">||</span> Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">==</span> MAXINT<span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dist<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000040;">+</span> Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">&lt;</span> Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Negative Length Cycle Detected!&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
            <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #666666;">//~ 下面代码供测试用</span>
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>to<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> rp <span style="color: #000080;">=</span> to<span style="color: #008080;">;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot; &quot;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>rp <span style="color: #000040;">!</span><span style="color: #000080;">=</span> start<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 反向输出路径</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>rp<span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot; &lt;- &quot;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dist<span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">==</span> MAXINT<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
            rp <span style="color: #000080;">=</span> Dist<span style="color: #008000;">&#91;</span>rp<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">src</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>start<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/shortest-path-bellman-ford/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[C++]临时对象的可变性</title>
		<link>http://www.dutor.net/index.php/2010/05/temp-obj-alter/</link>
		<comments>http://www.dutor.net/index.php/2010/05/temp-obj-alter/#comments</comments>
		<pubDate>Tue, 04 May 2010 12:04:19 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2245</guid>
		<description><![CDATA[　　有码有真相，各位看官您上眼：
<pre lang="cpp" line="1">
int main()
{
	bar(++foo(372)); //~ 此行报错
	bar(++foo(wrap_int(372))); //~ 无错
	return 0;
}
</pre>
　　第一个bar调用中foo返回int型临时对象，想要把这个int临时对象++后传给bar，未遂。第二个bar调用中，foo返回一个包装过的int, 即wrap_int，对这个临时对象进行++(重载)，得逞。<strong>结论：C++中，基本类型（内置类型）的临时对象不可以作为左值（l-value），即不可以修改；用户自定义类型的临时对象可以作为左值。</strong>]]></description>
			<content:encoded><![CDATA[<p>　　有码有真相，各位看官您上眼：</p>

<div class="wp_codebox"><table><tr id="p224531"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2245code31"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> foo<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">struct</span> wrap_int
<span style="color: #008000;">&#123;</span>
	wrap_int<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> _n<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> n<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
	operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> n<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
	operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #0000ff;">const</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> n<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
	wrap_int operator <span style="color: #000040;">++</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #000040;">++</span>n<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">int</span> n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
wrap_int foo<span style="color: #008000;">&#40;</span>wrap_int n<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	bar<span style="color: #008000;">&#40;</span><span style="color: #000040;">++</span>foo<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 此行报错</span>
	bar<span style="color: #008000;">&#40;</span><span style="color: #000040;">++</span>foo<span style="color: #008000;">&#40;</span>wrap_int<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 无错</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　第一个bar调用中foo返回int型临时对象，想要把这个int临时对象++后传给bar，未遂。第二个bar调用中，foo返回一个包装过的int, 即wrap_int，对这个临时对象进行++(重载)，得逞。<strong>结论：C++中，基本类型（内置类型）的临时对象不可以作为左值（l-value），即不可以修改；用户自定义类型的临时对象可以作为左值。</strong><br />
　　再看：</p>

<div class="wp_codebox"><table><tr id="p224532"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2245code32"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> vec<span style="color: #008080;">;</span>
    vec.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vec.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">4</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vec.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vec.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vec.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    sort<span style="color: #008000;">&#40;</span><span style="color: #000040;">++</span>vec.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, vec.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    deque<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> deq<span style="color: #008080;">;</span>
    deq.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    deq.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">4</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    deq.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    deq.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    deq.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    sort<span style="color: #008000;">&#40;</span><span style="color: #000040;">++</span>deq.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, deq.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>这段代码中，对deque的排序没有问题，而对vec的排序操作就<strong>可能</strong>造成和上例类似的错误。因为vector<int>::iterator<strong>很可能</strong>会以裸露的指针来实现，这时对vec.begin()进行++操作就会出错。而对于deque，由于其特殊的内存模型，其iterator不可能是普通的指针，也就不存在这种错误。<br />
~over</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/05/temp-obj-alter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>出栈序列计数</title>
		<link>http://www.dutor.net/index.php/2010/04/catalan-count/</link>
		<comments>http://www.dutor.net/index.php/2010/04/catalan-count/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 11:39:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[数理空间]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2222</guid>
		<description><![CDATA[　　现有一个数列$$S = \{1,2,3,\ldots,n\}$$，另有一个栈Stack和一个队列Queue，Stack与Queue初始为空。现对S中元素依次进行如下操作：
<ol>
	<li>若Stack为空，则从S中取出一个元素入栈；</li>
	<li>若Stack非空，则有两种选择：将栈顶元素弹出并入队，或者从S中取出一个元素入栈；</li>
	<li>若S元素已经取完则操作结束，否则执行操作1或2。</li>
</ol>
　　问最终队列Queue有多少种排列情况？聪明且见识广博的你或许一下子就可以说出答案：$$\120dpi \color{red}\frac{C_{2n}^{n}}{n+1}\quad\textbf{or}\quad\frac{\binom{2n}{n}}{n+1}$$
　　现在对这个结果进行证明。
　　设1表示入栈操作，0表示出栈操作。那么上面对n个元素的入栈和出栈操作就构成了长度为2n的由0和1组成的序列，其中1和0的个数均为n个，在没有任何限制的情况下，一共有$$C_{2n}^n$$个这样的序列。但是，这里的01序列是建立在一些列的入栈出栈操作的基础上的，因此就会受到入栈、出栈操作的限制。这里，唯一的限制就是栈为空时，无法进行出栈操作。反映到这个01序列中就是，任意位置之前，0的个数都能比1的个数多。因为有了01序列的总数$$C_{2n}^n$$，所以为了找出满足条件的序列的个数，只需要找出不符合条件的序列的个数。]]></description>
			<content:encoded><![CDATA[<p>　　现有一个数列<img src="http://www.dutor.net/wp-content/cache/6c8ed79ba0c420a15eb059d708d93f25.png" align="absmiddle" class="tex" alt="S = \{1,2,3,\ldots,n\}" />，另有一个栈Stack和一个队列Queue，Stack与Queue初始为空。现对S中元素依次进行如下操作：</p>
<ol>
<li>若Stack为空，则从S中取出一个元素入栈；</li>
<li>若Stack非空，则有两种选择：将栈顶元素弹出并入队，或者从S中取出一个元素入栈；</li>
<li>若S元素已经取完则操作结束，否则执行操作1或2。</li>
</ol>
<p>　　问最终队列Queue有多少种排列情况？聪明且见识广博的你或许一下子就可以说出答案：<img src="http://www.dutor.net/wp-content/cache/d51374e717cdc01e07e23bc4689decd7.png" align="absmiddle" class="tex" alt="\120dpi \color{red}\frac{C_{2n}^{n}}{n+1}\quad\textbf{or}\quad\frac{\binom{2n}{n}}{n+1}" /><br />
　　现在对这个结果进行证明。<br />
　　设1表示入栈操作，0表示出栈操作。那么上面对n个元素的入栈和出栈操作就构成了长度为2n的由0和1组成的序列，其中1和0的个数均为n个，在没有任何限制的情况下，一共有<img src="http://www.dutor.net/wp-content/cache/e659e4628b3668b3c4762011fbab3311.png" align="absmiddle" class="tex" alt="C_{2n}^n" />个这样的序列。但是，这里的01序列是建立在一些列的入栈出栈操作的基础上的，因此就会受到入栈、出栈操作的限制。这里，唯一的限制就是栈为空时，无法进行出栈操作。反映到这个01序列中就是，任意位置之前，0的个数都能比1的个数多。因为有了01序列的总数<img src="http://www.dutor.net/wp-content/cache/e659e4628b3668b3c4762011fbab3311.png" align="absmiddle" class="tex" alt="C_{2n}^n" />，所以为了找出满足条件的序列的个数，只需要找出不符合条件的序列的个数。<br />
　　假设我们现在找到这样一个不符合条件的序列，那么这个序列中一定存在这样一个最小的位置k，k之前1的个数为m，0的个数为m+1。那么k之后1的个数就是n-m，0的个数为n-m-1。现在我们把k后面的01序列进行取反操作，即0变成1、1变成0。此时整个序列中有n-1个1，n+1个0。由构造过程可知，每一个<strong>不满足条件</strong>的01序列都唯一地对应一个长度为2n、含有n-1个1、n+1个0的序列。有上述变换的逆操作易知，每一个长度为2n、含有n-1个1、n+1个0的序列都唯一地对应一个不满足条件的01序列。而长度为2n、含有n-1个1、n+1个0的序列得个数为<img src="http://www.dutor.net/wp-content/cache/91f17fe6ab5ae122226bd4fa9b013501.png" align="absmiddle" class="tex" alt="C_{2n}^{n-1}" />。最后我们就证明了，满足条件的01序列的个数为：<br />
<img src="http://www.dutor.net/wp-content/cache/e6f0f33784fd05dda096ae9b2fabfc7d.png" align="absmiddle" class="tex" alt="\120dpi \color{red} C_n = C_{2n}^{n}-C_{2n}^{n-1} = C_{2n}^{n}-C_{2n}^{n+1} = \frac{1}{n+1}C_{2n}^{n}" /><br />
　　这个式子所表示的数列（设为h）叫做<a href="http://zh.wikipedia.org/zh/%E5%8D%A1%E5%A1%94%E5%85%B0%E6%95%B0" target="_blank">卡特兰数（catalan）</a>，它具有这样一个特性：<br />
<img src="http://www.dutor.net/wp-content/cache/567062184aa5206cdf30877b6ba55a77.png" align="absmiddle" class="tex" alt="\begin{array}{rcl}h[0]&#038;=&#038;1 \\h[1]&#038;=&#038;1 \\h[n+1]&#038;=&#038;\sum_{i=0}^n h[i]\cdot h[n-i]\end{array}" /><br />
　　还有很多经典问题都可以用卡特兰数来表示，比如矩阵乘法、二叉计数、单调路径等，关于这些问题的原型，请Google之。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/catalan-count/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[STL]函数对象/仿函数</title>
		<link>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/</link>
		<comments>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 12:37:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[STL]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2209</guid>
		<description><![CDATA[　　提到C++ STL，首先被人想到的是它的三大组件：Containers, Iterators, Algorithms，即容器，迭代器和算法。容器为用户提供了常用的数据结构，算法大多是独立于容器的常用的基本算法，迭代器是由容器提供的一种接口，算法通过迭代器来操控容器。接下来要介绍的是另外的一种组件，函数对象（Function Object，JJHou译作Functor仿函数）。
<h4>什么是函数对象</h4>
　　顾名思义，函数对象首先是一个对象，即某个类的实例。其次，函数对象的行为和函数一致，即是说可以像调用函数一样来使用函数对象，如参数传递、返回值等。这种行为是通过重载类的()操作符来实现的，举例说明之，
<pre lang="cpp" line="1">
class Print
{
public:
    void operator()(int n)
    {
        std::cout<<n<<std::endl;
        return ;
    }
};
int
main(int argc, char **argv)
{
    Print print;
    print(372);
    print.operator()(372); //~ 显式调用
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　提到C++ STL，首先被人想到的是它的三大组件：Containers, Iterators, Algorithms，即容器，迭代器和算法。容器为用户提供了常用的数据结构，算法大多是独立于容器的常用的基本算法，迭代器是由容器提供的一种接口，算法通过迭代器来操控容器。接下来要介绍的是另外的一种组件，函数对象（Function Object，JJHou译作Functor仿函数）。</p>
<h4>什么是函数对象</h4>
<p>　　顾名思义，函数对象首先是一个对象，即某个类的实例。其次，函数对象的行为和函数一致，即是说可以像调用函数一样来使用函数对象，如参数传递、返回值等。这种行为是通过重载类的()操作符来实现的，举例说明之，</p>

<div class="wp_codebox"><table><tr id="p220933"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code" id="p2209code33"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Print
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>n<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Print print<span style="color: #008080;">;</span>
    print<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    print.<span style="color: #007788;">operator</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 显式调用</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　其实我们早就开始使用函数对象了，当你写下sort(v.begin(), v.end())时(假定v是vector&lt;int&gt;)，其实调用的是sort(v.begin(), v.end(), less&lt;int&gt;())，这样sort就会将v从小至大排序。若要逆向排序，你就需要显式地为sort指定一个排序规则，即函数对象greater&lt;int&gt;(). less&lt;T&gt;和greater&lt;T&gt;是STL中的两个模板类，它们使用类型T的&lt;和&gt;操作符。less&lt;T&gt;的一个典型实现可能是这样的：</p>

<div class="wp_codebox"><table><tr id="p220934"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code" id="p2209code34"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> less
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span>l, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span>r<span style="color: #008000;">&#41;</span><span style="color: #0000ff;">const</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&lt;</span> r<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<h4>函数对象的分类</h4>
<p>　　根据用途和参数特征，STL中的函数对象通常分为以下几类：Predicates, Arithmetic Function Objects, Binders, Negaters, Member Function Adapters, Pointer to Function Adapters。下面逐一介绍一下，之前得先介绍两个基类：</p>

<div class="wp_codebox"><table><tr id="p220935"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p2209code35"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Arg, <span style="color: #0000ff;">class</span> Res<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">struct</span> unary_function <span style="color: #666666;">//~ 一元函数对象基类</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">typedef</span> Arg argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Res result_type<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Arg1, <span style="color: #0000ff;">class</span> Arg2, <span style="color: #0000ff;">class</span> Res<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">struct</span> binary_function <span style="color: #666666;">//~ 二元函数对象基类</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">typedef</span> Arg1 first_argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Arg2 second_argument_type<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typedef</span> Res  result_type<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>使用这两个基类，首先需要包含头文件<functional>。</p>
<h5>Predicates</h5>
<p>　　Predicate是一种函数对象，返回值（应该是operator()的返回值）为布尔型，接受一个或者两个参数。通常用来判断对象的有效性（一个参数时）或者对两个对象进行比较（如less）。你可以根据自己的需要定义自己的Predicate，但STL已经定义了一些Predicate，你可以直接使用。</p>
<table>
<caption>Predicates</caption>
<tr>
<th>Predicate</th>
<th>类型</th>
<th>描述</th>
</tr>
<tr>
<td>equal_to<type>()</td>
<td>Binary</td>
<td>使用==判等</td>
</tr>
<tr>
<td>not_equal_to<type>()</td>
<td>Binary</td>
<td>使用!=判等</td>
</tr>
<tr>
<td>less<type>()</td>
<td>Binary</td>
<td>使用< </td>
</tr>
<tr>
<td>greater<type>()</td>
<td>Binary</td>
<td>使用> </td>
</tr>
<tr>
<td>less_equal<type>()</td>
<td>Binary</td>
<td>使用<= </td>
</tr>
<tr>
<td>greater_equal<type>()</td>
<td>Binary</td>
<td>使用>= </td>
</tr>
<tr>
<td>logical_not<type>()</td>
<td>Unary</td>
<td>使用!逻辑取反</td>
</tr>
<tr>
<td>logical_and<type>()</td>
<td>Binary</td>
<td>使用&#038;&#038;逻辑与</td>
</tr>
<tr>
<td>logical_or<type>()</td>
<td>Binary</td>
<td>使用||逻辑或</td>
</tr>
</table>
<h5>算术运算函数对象</h5>
<p>　　进行简单的算术运算，这类函数对象我用的很少，通常是自己定义。</p>
<table>
<caption>算术运算函数对象</caption>
<tr>
<th>函数对象</th>
<th>类型</th>
<th>描述</th>
</tr>
<tr>
<td>negate<type>()</td>
<td>Unary</td>
<td>使用-求负</td>
</tr>
<tr>
<td>plus<type>()</td>
<td>Binary</td>
<td>使用+加法</td>
</tr>
<tr>
<td>minus<type>()</td>
<td>Binary</td>
<td>使用-减法</td>
</tr>
<tr>
<td>multiplies<type>()</td>
<td>Binary</td>
<td>使用*乘法</td>
</tr>
<tr>
<td>divides<type>()</td>
<td>Binary</td>
<td>使用/除法</td>
</tr>
<tr>
<td>modulus<type>()</td>
<td>Binary</td>
<td>使用%求余</td>
</tr>
</table>
<h5>绑定Binders</h5>
<p>　　有两种绑定bind1st和bind2nd，它们可以将一个二元函数对象的其中一个参数绑定为某个已知的对象，从而得到一个一元函数对象。例如要在vector&lt;int&gt; v中查找等于372的值的位置，我可以将372绑定到equal_to&lt;int&gt;()的第一个或者第二个参数：</p>

<div class="wp_codebox"><table><tr id="p220936"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2209code36"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> v<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">1000</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        v.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it<span style="color: #008080;">;</span>
    it <span style="color: #000080;">=</span> find_if<span style="color: #008000;">&#40;</span>v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, bind1st<span style="color: #008000;">&#40;</span>equal_to<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">372</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>it<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　其实，这里的bind1st和bind2nd并不是函数对象，只是模板函数而已。这两个函数分别返回类型为binder1st和binder2nd的函数对象。下面的代码，聪明的你肯定一看就懂：</p>

<div class="wp_codebox"><table><tr id="p220937"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2209code37"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// bind1st</span>
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op<span style="color: #000080;">&gt;</span> 
<span style="color: #0000ff;">class</span> binder1st <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> unary_function
                  <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span>,
                   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span><span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
   Op op_<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span> first_arg_<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
      binder1st<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span><span style="color: #000040;">&amp;</span>
                first_arg<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> op_<span style="color: #008000;">&#40;</span>op<span style="color: #008000;">&#41;</span>,
               first_arg_<span style="color: #008000;">&#40;</span>first_arg<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
      <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span><span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
   <span style="color: #008000;">&#123;</span>
      <span style="color: #0000ff;">return</span> op_<span style="color: #008000;">&#40;</span>first_arg_, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op, <span style="color: #0000ff;">class</span> Arg<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> binder1st<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span> bind1st<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                             <span style="color: #0000ff;">const</span> Arg<span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">return</span> binder1st<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>op, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #666666;">// bind2nd</span>
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">class</span> binder2nd <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> unary_function
   <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">first_argument_type</span>,
    <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span><span style="color: #000080;">&gt;</span>
<span style="color: #008000;">&#123;</span>
   Op op_<span style="color: #008080;">;</span>
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span> second_arg_<span style="color: #008080;">;</span>
&nbsp;
   <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
      binder2nd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">second_argument_type</span><span style="color: #000040;">&amp;</span>
                                   second_arg<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> op_<span style="color: #008000;">&#40;</span>op<span style="color: #008000;">&#41;</span>,
                                   second_arg_<span style="color: #008000;">&#40;</span>second_arg<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
   <span style="color: #0000ff;">typename</span> Op<span style="color: #008080;">::</span><span style="color: #007788;">result_type</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">typename</span>
      Op<span style="color: #008080;">::</span><span style="color: #007788;">argument_type</span><span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
   <span style="color: #008000;">&#123;</span>
      <span style="color: #0000ff;">return</span> op_<span style="color: #008000;">&#40;</span>arg, second_arg_<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> Op, <span style="color: #0000ff;">class</span> Arg<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> binder2nd<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span> bind2nd<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Op<span style="color: #000040;">&amp;</span> op,
                             <span style="color: #0000ff;">const</span> Arg<span style="color: #000040;">&amp;</span> arg<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #0000ff;">return</span> binder2nd<span style="color: #000080;">&lt;</span>Op<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>op, arg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<h5>Negaters</h5>
<p>　　Negater是针对Predicate设计的，它简单的将Predicate的返回值取反。有两个Negater，not1和not2，分别对一元和二元Predicate取反。</p>
<h5>Member Function Adapters</h5>
<p>　　有时候，你可能想让算法调用容器元素的成员函数，而不是外部函数。因为外部无法改变对象内的状态，且内部函数通常具有更高的效率。例如swap(string, string)总是没有string.swap(string)快速。又比如sort无法对list进行排序，这时候只能使用list.sort()来给链表排序。这时候就需要使用一定的方法将对象内部的函数“变成”函数对象，这样的函数对象叫做成员函数适配器，其实前面的binder也是一种适配器。看下面的例子：</p>

<div class="wp_codebox"><table><tr id="p220938"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code" id="p2209code38"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> v<span style="color: #008080;">;</span>
    v.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>it <span style="color: #000080;">=</span> v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">20</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, i<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    for_each<span style="color: #008000;">&#40;</span>v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">mem_fun_ref</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">sort</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>it <span style="color: #000080;">=</span> v.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> v.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>list<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> lt<span style="color: #008080;">;</span> lt <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>it<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>lt<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>lt<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>上面的例子中，遍历vector&lt;list&lt;int&gt; &gt;并对链表进行排序。其中使用的是成员函数适配器mem_fun_ref，它返回的函数对象会以list&lt;int&gt;对象的引用为参数。另外一个mem_fun则是以指向list&lt;int&gt;对象的指针为参数。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/stl-functor-function-object/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[C++]exit &amp; abort &amp; 析构 &amp; 异常</title>
		<link>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/</link>
		<comments>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 12:20:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[OS基础]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2187</guid>
		<description><![CDATA[<h4>进程之死</h4>
　　对于一个用C++写的程序，被加载至内存后运行，最终走向死亡。程序的死亡大致有三种：
<ul>
	<li><strong>自然死亡</strong>，即无疾而终，通常就是main()中的一个return 0;</li>
	<li><strong>自杀</strong>，当程序发现自己再活下去已经没有任何意义时，通常会选择自杀。当然，这种自杀也是一种请求式的自杀，即请求OS将自己毙掉。有两种方式：void exit(int status)和void abort(void)。</li>
	<li><strong>他杀</strong>，同现实不同的是，程序家族中的他杀行径往往是由自己至亲完成的，通常这个至亲就是他的生身父亲（还是母亲？）。C++并没有提供他杀的凶器，这些凶器往往是由OS直接或者间接（通过一些进程库，如pthread）提供的。</li>
</ul>
　　自然死是最完美的结局，他杀是我们最不愿意看到的，自杀虽是迫不得已，但主动权毕竟还是由程序自己掌控的。下面探究程序一下不同的死亡方式对对象的析构有何影响。]]></description>
			<content:encoded><![CDATA[<h4>进程之死</h4>
<p>　　对于一个用C++写的程序，被加载至内存后运行，最终走向死亡。程序的死亡大致有三种：</p>
<ul>
<li><strong>自然死亡</strong>，即无疾而终，通常就是main()中的一个return 0;</li>
<li><strong>自杀</strong>，当程序发现自己再活下去已经没有任何意义时，通常会选择自杀。当然，这种自杀也是一种请求式的自杀，即请求OS将自己毙掉。有两种方式：void exit(int status)和void abort(void)。</li>
<li><strong>他杀</strong>，同现实不同的是，程序家族中的他杀行径往往是由自己至亲完成的，通常这个至亲就是他的生身父亲（还是母亲？）。C++并没有提供他杀的凶器，这些凶器往往是由OS直接或者间接（通过一些进程库，如pthread）提供的。</li>
</ul>
<p>　　自然死是最完美的结局，他杀是我们最不愿意看到的，自杀虽是迫不得已，但主动权毕竟还是由程序自己掌控的。下面探究程序一下不同的死亡方式对对象的析构有何影响。</p>
<h4>程序死亡方式对对象析构的影响</h4>
<p>　　C++程序中大致有三种对象：全局对象、局部静态对象、局部非静态对象（自动对象）。举例说明之：</p>

<div class="wp_codebox"><table><tr id="p218739"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2187code39"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Foo
<span style="color: #008000;">&#123;</span>
    Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    ~Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;~Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #ff0000; font-style: italic;">/* some other sources here */</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
Foo Global<span style="color: #008080;">;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">static</span> Foo StaticLocal<span style="color: #008080;">;</span>
    Foo Local<span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ quit();</span>
    <span style="color: #666666;">//~ abort();</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Foo AnotherLocal<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　编译运行这个程序，程序将正常退出。运行过程中，Global对象在进入main之前首先被构造，其次是StaticLocal和Local。main函数退出之前，Local和StaticLocal被析构，main退出后Global也将被析构。<br />
　　如果将17行处quit()的注释去掉，我们将会看到4个对象被构造，但却只有两个对象被析构，分别是Global和StaticLocal对象，其他两个对象Local和AnotherLocal对象的析构函数将不会被调用。<br />
　　如果将18行处abort()的注释去掉（quit()被注释），3个对象对象被构造，但在程序退出之前没有任何一个对象的析构函数被调用。<br />
　　也就是说，正常情况下，所有类型的对象都将被析构；由exit退出时只有非自动对象被析构；abort被调用时，程序将直接退出，任何对象的析构函数都不会调用。下面着重介绍下exit的行为。</p>
<h4>exit做了什么</h4>
<p>　　介绍exit之前，不得不提void atexit(void (*f)(void) )函数。atexit，顾名思义，它描述了exit里面要做些什么。可以看出，它接受一个void f(void)形式的函数的指针。使用atexit我们可以向exit注册一些列的函数，这些函数在exit中被调用，调用的顺序与它们被注册的顺序相反。你可以使用下面的代码来验证：</p>

<div class="wp_codebox"><table><tr id="p218740"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2187code40"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> f1<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;f1&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> f2<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;f2&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">atexit</span><span style="color: #008000;">&#40;</span>f1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">atexit</span><span style="color: #008000;">&#40;</span>f2<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　void exit(int status)被调用时，它首先调用全局的或者静态的对象的析构函数，然后调用atexit所注册的函数。如果这些函数中的某一个再次调用exit，your nightmare is coming。最后，exit会将代表程序执行状态的status<strong>“返回”</strong>（确切的说应该叫做传递，因为exit永远不会返回调用方）给当前程序的父进程。<br />
　　值得一提的是，执行exit结束程序，虽然自动对象的析构函数不被调用，但当程序结束时，OS会将该程序占用的资源全部释放。这些资源包括该程序申请的内存（堆）、打开的文件句柄、管道（Unix/Linux）、socket等。这样一来，似乎那些析构函数不被调用并不会有什么问题。确实，但可惜这只适用于单线程的程序。对于多线程程序来说，只有当整个进程结束时，它占用的资源才会被OS释放，这时某个线程的exit就可能带来麻烦（比如内存泄露）。怎么办呢？</p>
<h4>使用异常</h4>
<p>　　使用C++提供的异常机制，可以很好的解决上面提出的问题。我们可以在需要exit的地方抛出（throw）异常，然后在捕获（catch）异常处调用exit，这样，所有需要的析构函数都将被调用。代码通常是这个样子滴：</p>

<div class="wp_codebox"><table><tr id="p218741"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2187code41"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;cstdlib&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Foo
<span style="color: #008000;">&#123;</span>
    Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    ~Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;~Foo&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #ff0000; font-style: italic;">/* some other sources here */</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">struct</span> except<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> exception
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> what<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">throw</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">&quot;except&quot;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
Foo Global<span style="color: #008080;">;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">try</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">static</span> Foo StaticLocal<span style="color: #008080;">;</span>
        Foo Local<span style="color: #008080;">;</span>
        quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">catch</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> exception<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cerr</span><span style="color: #000080;">&lt;&lt;</span>e.<span style="color: #007788;">what</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
        <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Foo AnotherLocal<span style="color: #008080;">;</span>
    <span style="color: #666666;">//~ exit(1);</span>
    <span style="color: #0000ff;">throw</span> except<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>输出：</p>
<pre>
Foo
Foo
Foo
Foo
~Foo
~Foo
except
~Foo
~Foo
</pre>
<p><strong>补充：</strong>还有一个与atexit()相似的函数叫on_exit()，Google之。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/exit-abort-des-except/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>单源最短路径Dijkstra算法</title>
		<link>http://www.dutor.net/index.php/2010/04/shortest-path-dijkstra/</link>
		<comments>http://www.dutor.net/index.php/2010/04/shortest-path-dijkstra/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 11:36:24 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[图论]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2180</guid>
		<description><![CDATA[<h4>Dijkstra算法简述</h4>
　　Dijkstra算法是图论中的一种求单源最短路的算法，即从一个点开始到所有其他点的最短路。其基本原理是：集合T包含所有当前已经找到最短路径的点，初始情况下T中只有源点。U维护当前源点通过T中各点到达其他各点的距离。从源点开始，每次新扩展一个属于U、距离T中点最短的点，用该点更新U中的与其相邻的点的距离。当所有边权都为正时，由于不会存在一个距离更短的没扩展过的点，所以这个点的距离永远不会再被改变，因而保证了算法的正确性。不过根据这个原理，用Dijkstra求最短路的图不能有负权边，因为扩展到负权边的时候会产生更短的距离，有可能就破坏了已经更新的点距离不会改变的性质。若要处理含有负权值边的情况，就需要使用<a href="http://www.dutor.net/index.php/2010/05/shortest-path-bellman-ford/" target="_blank">Bellman-Ford算法</a>了。
<h4>Dijkstra算法流程</h4>
　　在以下说明中，start为源，Adj[u,v]为点u和v之间的边的长度，结果保存在Closest[]
<ul>
	<li>初始化：源的距离Closest[start]设为0，其他的点距离设为无穷大，同时把所有的点的状态设为没有扩展过。</li>
	<li>以下过程循环n-1次：
在没有扩展过的点中取一距离最小的点u，并将其状态设为已扩展。
对于每个与u相邻的点v，如果Closest[u]+Adj[u,v] < Closest[v]，那么把Closest[v]更新成更短的距离Closest[u]+Adj[u,v]。此时到点v的最短路径上，前一个节点即为u。</li>
	<li>结束。此时对于任意的u，Closest[u]就是start到u的距离。</li>
</ul>]]></description>
			<content:encoded><![CDATA[<h4>Dijkstra算法简述</h4>
<p>　　Dijkstra算法是图论中的一种求单源最短路的算法，即从一个点开始到所有其他点的最短路。其基本原理是：集合T包含所有当前已经找到最短路径的点，初始情况下T中只有源点。U维护当前源点通过T中各点到达其他各点的距离。从源点开始，每次新扩展一个属于U、距离T中点最短的点，用该点更新U中的与其相邻的点的距离。当所有边权都为正时，由于不会存在一个距离更短的没扩展过的点，所以这个点的距离永远不会再被改变，因而保证了算法的正确性。不过根据这个原理，用Dijkstra求最短路的图不能有负权边，因为扩展到负权边的时候会产生更短的距离，有可能就破坏了已经更新的点距离不会改变的性质。若要处理含有负权值边的情况，就需要使用<a href="http://www.dutor.net/index.php/2010/05/shortest-path-bellman-ford/" target="_blank">Bellman-Ford算法</a>了。</p>
<h4>Dijkstra算法流程</h4>
<p>　　在以下说明中，start为源，Adj[u,v]为点u和v之间的边的长度，结果保存在Closest[]</p>
<ul>
<li>初始化：源的距离Closest[start]设为0，其他的点距离设为无穷大，同时把所有的点的状态设为没有扩展过。</li>
<li>以下过程循环n-1次：<br />
在没有扩展过的点中取一距离最小的点u，并将其状态设为已扩展。<br />
对于每个与u相邻的点v，如果Closest[u]+Adj[u,v] < Closest[v]，那么把Closest[v]更新成更短的距离Closest[u]+Adj[u,v]。此时到点v的最短路径上，前一个节点即为u。</li>
<li>结束。此时对于任意的u，Closest[u]就是start到u的距离。</li>
</ul>
<h4>Dijkstra算法C++实现</h4>

<div class="wp_codebox"><table><tr id="p218042"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2180code42"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
&nbsp;
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> MAXINT <span style="color: #000080;">=</span> <span style="color: #208080;">0xFFFF</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 不可达的路径长度上限</span>
<span style="color: #0000ff;">class</span> Node
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    Node<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> w<span style="color: #008000;">&#40;</span>MAXINT<span style="color: #008000;">&#41;</span>, v<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">int</span> src, <span style="color: #666666;">//~ 最短路径上的上一个顶点</span>
        w<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 到该节点的路径长度</span>
    <span style="color: #0000ff;">bool</span> v<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 标识该节点是否已经加入最短路径集</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    vector<span style="color: #000080;">&lt;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000080;">&gt;</span> Adj<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> n, <span style="color: #666666;">// 顶点数</span>
        m, <span style="color: #666666;">//~ 边数</span>
        from,
        to,
        w,
        min <span style="color: #000080;">=</span> MAXINT,
        start, <span style="color: #666666;">//~ 源点</span>
        k<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 下一个可以加入的顶点号</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>n<span style="color: #008080;">;</span>
    vector<span style="color: #000080;">&lt;</span>Node<span style="color: #000080;">&gt;</span> Closest<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> n<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        Adj.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>n, MAXINT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Adj<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>m<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> m<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>from<span style="color: #000080;">&gt;&gt;</span>to<span style="color: #000080;">&gt;&gt;</span>w<span style="color: #008080;">;</span>
        Adj<span style="color: #008000;">&#91;</span>from<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>to<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> w<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>start<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 从顶点start开始的最短路径</span>
    Closest<span style="color: #008000;">&#91;</span>start<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~</span>
    k <span style="color: #000080;">=</span> start<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span> <span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> n<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        min <span style="color: #000080;">=</span> MAXINT<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> t<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 维护下一个可以加入最短路径集的顶点</span>
        Closest<span style="color: #008000;">&#91;</span>k<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">v</span> <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 加入最短路径集</span>
        <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> j <span style="color: #000080;">&lt;</span> n<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>j<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 更新Closest和k</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">&gt;</span> Closest<span style="color: #008000;">&#91;</span>k<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000040;">+</span> Adj<span style="color: #008000;">&#91;</span>k<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">=</span> Closest<span style="color: #008000;">&#91;</span>k<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000040;">+</span> Adj<span style="color: #008000;">&#91;</span>k<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
                Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">src</span> <span style="color: #000080;">=</span> k<span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span> <span style="color: #000080;">&lt;</span> min <span style="color: #000040;">&amp;&amp;</span> <span style="color: #000040;">!</span>Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">v</span><span style="color: #008000;">&#41;</span>
            <span style="color: #008000;">&#123;</span>
                min <span style="color: #000080;">=</span> Closest<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span><span style="color: #008080;">;</span>
                t <span style="color: #000080;">=</span> j<span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>min <span style="color: #000080;">==</span> MAXINT<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 剩下的顶点不可达</span>
        k <span style="color: #000080;">=</span> t<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #666666;">//~ 下面代码供测试用</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> n<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>Closest<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">w</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\t</span>'</span><span style="color: #000080;">&lt;&lt;</span>boolalpha<span style="color: #000080;">&lt;&lt;</span>Closest<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">v</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>to<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> rp <span style="color: #000080;">=</span> to<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>rp <span style="color: #000040;">!</span><span style="color: #000080;">=</span> start<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 反向输出路径</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>rp<span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot; &lt;- &quot;</span><span style="color: #008080;">;</span>
            rp <span style="color: #000080;">=</span> Closest<span style="color: #008000;">&#91;</span>rp<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">src</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>start<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/shortest-path-dijkstra/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[C++]覆盖std内的名字</title>
		<link>http://www.dutor.net/index.php/2010/04/name-look-up/</link>
		<comments>http://www.dutor.net/index.php/2010/04/name-look-up/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 08:07:08 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2171</guid>
		<description><![CDATA[　　在现行的C++标准中有这么一个名字，std，它是一个namespace(命名空间)。C++标准库的所有类型/对象/函数/模板都定义在这个命名空间中。关于"What namespace? Why namespace? How namespace?" 的问题，任何一本基础的C++读物中都会有介绍，此处略过。为了使用std内定义的对象，可供使用的语法无非是
<pre lang="cpp" line="1">
std::vector<int> ivec;
//~ or
using std::vector;
vector<int> ivec;
//~ or
using namespace std;
vector<int> ivec;
</pre>
　　现在有这样一种需要，我想为std内的某种类型(比如string)重载操作符，而不想使用std内为我们提供的版本。]]></description>
			<content:encoded><![CDATA[<p>　　在现行的C++标准中有这么一个名字，std，它是一个namespace(命名空间)。C++标准库的所有类型/对象/函数/模板都定义在这个命名空间中。关于&#8221;What namespace? Why namespace? How namespace?&#8221; 的问题，任何一本基础的C++读物中都会有介绍，此处略过。为了使用std内定义的对象，可供使用的语法无非是</p>

<div class="wp_codebox"><table><tr id="p217143"><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code" id="p2171code43"><pre class="cpp" style="font-family:monospace;">std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span>
<span style="color: #666666;">//~ or</span>
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #008080;">;</span>
vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span>
<span style="color: #666666;">//~ or</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> ivec<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>　　现在有这样一种需要，我想为std内的某种类型(比如string)重载操作符，而不想使用std内为我们提供的版本。很简单：</p>

<div class="wp_codebox"><table><tr id="p217144"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code" id="p2171code44"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 逆天而行了 :-)</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>string<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;dutor&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;</span>string<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;ivan&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　运行这段代码，确实会得到我们想要的结果，dutor > ivan. 但是对于std内其他使用string的operator<()的对象还会这样吗？</p>

<div class="wp_codebox"><table><tr id="p217145"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2171code45"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    set<span style="color: #000080;">&lt;</span>string<span style="color: #000080;">&gt;</span> Set<span style="color: #008080;">;</span>
    Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;ivan&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;dutor&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>set<span style="color: #000080;">&lt;</span>string<span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> it <span style="color: #000080;">=</span> Set.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            it <span style="color: #000040;">!</span><span style="color: #000080;">=</span> Set.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>it<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #000040;">*</span>it<span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　这次ivan会在dutor前面输出吗？很遗憾，dutor被首先输出。不要忘了，std内还有一个operator<(const string&#038;, const string&#038;)呢！set调用的正是std里面的版本！那么我们有什么办法可以让set调用我们自己的operator<()呢？这涉及到C++的名字查找机制，C++采用的是一种懒惰的名字查找机制，也可以说是一种非贪婪式的查找。以本例来说，set与原始版本的operator<同属于std命名空间，set就会就近使用这个版本，而不是我们的自定义版本，而我们在main中使用的却是自定义版本。<br />
　　现在如何让set使用自定义的operator<已经变得明朗了，我们仅仅需要把我们的这个operator<添加到std中：</p>

<div class="wp_codebox"><table><tr id="p217146"><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code" id="p2171code46"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">namespace</span> std<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">bool</span> operator<span style="color: #000080;">&lt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> l, <span style="color: #0000ff;">const</span> string<span style="color: #000040;">&amp;</span> r<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&gt;</span> r<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　关于C++的名字查找机制，这里提到的只是皮毛而已，很多参考资料中到都做了深入的描述，请自行查阅。</p>
<p>　　刚才在当当买书，又看到雷人的一幕（我为什么说又？）：<br />
<a href="http://www.dutor.net/index.php/2010/04/name-look-up/stl1/" rel="attachment wp-att-2174"><img src="http://www.dutor.net/wp-content/uploads/2010/04/stl1.png" alt="" title="stl1" width="446" height="200" class="aligncenter size-full wp-image-2174" /></a><br />
<a href="http://www.dutor.net/index.php/2010/04/name-look-up/stl2/" rel="attachment wp-att-2175"><img src="http://www.dutor.net/wp-content/uploads/2010/04/stl2.png" alt="" title="stl2" width="480" height="222" class="aligncenter size-full wp-image-2175" /></a><br />
实在想不通，这￥0.56是哪里来的？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/name-look-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最小生成树之Kruskal算法</title>
		<link>http://www.dutor.net/index.php/2010/04/kruskal/</link>
		<comments>http://www.dutor.net/index.php/2010/04/kruskal/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 02:56:56 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[图论]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2157</guid>
		<description><![CDATA[　　一个无向、加权、连通图的生成树是指这样一棵树，它包含该图所有的n个顶点，和该图边集E中的n-1个边。最小生成树就是该图所有生成树中各边权值之和（构造代价）最小的生成树。求指定图的最小生成树有多种算法，除了这里要介绍的Kruskal算法，还有Prim算法、Sollin算法等。
<h4>Kruskal算法描述</h4>
　　用Kruskal算法为无向加权连通图G构造最小生成树T的步骤如下：首先初始化T为一个包含所有n个顶点、0个边的森林，E为G的边集。每次从E中取出一条具有最小权值的边（并从E中删除改变），如果该边不与T中其他边构成回路，则将该边加入T，否则舍弃该边。重复上述操作至T中含有n-1条边，此时T即Kruskal算法构造出的最小生成树。
<h4>Kruskal算法证明</h4>
　　易证，对于一个无向加权连通图，总是存在一棵或以上的有限课生成树，而这些生成树中肯定存在至少一棵最小生成树。下面证明Kruskal算法构造的生成树是<strong>这些</strong>最小生成树中的一棵。
　　设T为Kruskal算法构造出的生成树，U是G的最小生成树。如果T==U那么证明结束。如果T != U，我们就需要证明T和U的构造代价相同。由于T != U，所以一定存在k > 0条边存在于T中，却不在U中。接下来，我们做k次变换，每次从T中取出一条不在U中的边放入U，然后删除U一条不在T中的边，最后使T和U的边集相同。每次变换中，把T中的一条边e加入U，同时删除U中的一条边f。e、f按如下规则选取：a). e是在T中却不在U中的边的<strong>最小</strong>的一条边；b). e加入U后，肯定构成唯一的一个环路，令f是这个环路中的一条边，但不在T中。f一定存在，因为T中没有环路。]]></description>
			<content:encoded><![CDATA[<p>　　一个无向、加权、连通图的生成树是指这样一棵树，它包含该图所有的n个顶点，和该图边集E中的n-1个边。最小生成树就是该图所有生成树中各边权值之和（构造代价）最小的生成树。求指定图的最小生成树有多种算法，除了这里要介绍的Kruskal算法，还有Prim算法、Sollin算法等。</p>
<h4>Kruskal算法描述</h4>
<p>　　用Kruskal算法为无向加权连通图G构造最小生成树T的步骤如下：首先初始化T为一个包含所有n个顶点、0个边的森林，E为G的边集。每次从E中取出一条具有最小权值的边（并从E中删除改变），如果该边不与T中其他边构成回路，则将该边加入T，否则舍弃该边。重复上述操作至T中含有n-1条边，此时T即Kruskal算法构造出的最小生成树。</p>
<h4>Kruskal算法证明</h4>
<p>　　易证，对于一个无向加权连通图，总是存在一棵或以上的有限课生成树，而这些生成树中肯定存在至少一棵最小生成树。下面证明Kruskal算法构造的生成树是<strong>这些</strong>最小生成树中的一棵。<br />
　　设T为Kruskal算法构造出的生成树，U是G的最小生成树。如果T==U那么证明结束。如果T != U，我们就需要证明T和U的构造代价相同。由于T != U，所以一定存在k > 0条边存在于T中，却不在U中。接下来，我们做k次变换，每次从T中取出一条不在U中的边放入U，然后删除U一条不在T中的边，最后使T和U的边集相同。每次变换中，把T中的一条边e加入U，同时删除U中的一条边f。e、f按如下规则选取：a). e是在T中却不在U中的边的<strong>最小</strong>的一条边；b). e加入U后，肯定构成唯一的一个环路，令f是这个环路中的一条边，但不在T中。f一定存在，因为T中没有环路。</p>
<p>　　这样的一次变换后，U仍然是一棵生成树。<br />
　　我们假设e权值小于f，这样变换后U的代价一定小于变换前U的代价，而这和我们之前假设U是最小生成树矛盾，因此e权值不小于f。<br />
　　再假设e权值大于f。由于f权值小于e，由Kruskal算法知，f在e之前从E中取出，但被舍弃了。一定是由于和权值小于等于f的边构成了环路。但是T中权值小于等于f（小于e）的边一定存在于U中，而f在U中却没有和它们构成环路，又推出矛盾。所以e权值不大于f。于是e权值等于f。<br />
　　这样，每次变换后U的代价都不变，所以K次变换后，U和T的边集相同，且代价相同，这样就证明了T也是最小生成树。由证明过程可以知道，最小生成树可以不是唯一的。</p>
<h4>Kruskal算法的C++实现</h4>
<p>　　利用最小堆来存储边集E，利用并-查集来判断向T中添加边是否构成环路。</p>

<div class="wp_codebox"><table><tr id="p215747"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2157code47"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Edge 
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">int</span> from, to, w<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 不要被假象迷惑，这里是无向图</span>
	Edge<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> f, <span style="color: #0000ff;">int</span> t, <span style="color: #0000ff;">int</span> _w<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> from<span style="color: #008000;">&#40;</span>f<span style="color: #008000;">&#41;</span>, to<span style="color: #008000;">&#40;</span>t<span style="color: #008000;">&#41;</span>, w<span style="color: #008000;">&#40;</span>_w<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
	<span style="color: #ff0000; font-style: italic;">/*
	//~ bool operator &lt;(const Edge&amp; e){ return w &lt; e.w; }
	bool operator &gt;(const Edge&amp; e){ return w &gt; e.w; }
	*/</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #666666;">//~ 为什么我把operator&lt;重载为成员会出错？</span>
<span style="color: #666666;">//~ bool operator &lt;(const Edge&amp; e1, const Edge&amp; e2){ return e1.w &lt; e2.w; }</span>
<span style="color: #0000ff;">bool</span> operator <span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Edge<span style="color: #000040;">&amp;</span> e1, <span style="color: #0000ff;">const</span> Edge<span style="color: #000040;">&amp;</span> e2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> e1.<span style="color: #007788;">w</span> <span style="color: #000080;">&gt;</span> e2.<span style="color: #007788;">w</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span> 
<span style="color: #0000ff;">bool</span> AddEdge<span style="color: #008000;">&#40;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">&amp;</span> V, <span style="color: #0000ff;">const</span> Edge<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	vector<span style="color: #000080;">&lt;</span>Edge<span style="color: #000080;">&gt;</span> E<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> from, to, w<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> n<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 顶点数</span>
	<span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>n<span style="color: #008080;">;</span>
	vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> V<span style="color: #008000;">&#40;</span>n<span style="color: #000040;">+</span><span style="color: #0000dd;">1</span>, <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 顶点并查集</span>
	<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>from<span style="color: #000080;">&gt;&gt;</span>to<span style="color: #000080;">&gt;&gt;</span>w<span style="color: #008000;">&#41;</span> E.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span>Edge<span style="color: #008000;">&#40;</span>from, to, w<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	make_heap<span style="color: #008000;">&#40;</span>E.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, E.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, greater<span style="color: #000080;">&lt;</span>Edge<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> count <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 已添加边数</span>
	<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>E.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Edge e <span style="color: #000080;">=</span> E<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>AddEdge<span style="color: #008000;">&#40;</span>V, e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 将成功添加的边输出</span>
		<span style="color: #008000;">&#123;</span>
			count<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
			<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>count <span style="color: #000080;">==</span> n <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 树已生成完毕</span>
			<span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>e.<span style="color: #007788;">from</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;-&gt;&quot;</span><span style="color: #000080;">&lt;&lt;</span>e.<span style="color: #007788;">to</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;: &quot;</span><span style="color: #000080;">&lt;&lt;</span>e.<span style="color: #007788;">w</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		pop_heap<span style="color: #008000;">&#40;</span>E.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, E.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,greater<span style="color: #000080;">&lt;</span>Edge<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		E.<span style="color: #007788;">pop_back</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>count <span style="color: #000040;">!</span><span style="color: #000080;">=</span> n <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;I cannot do what you want.&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> AddEdge<span style="color: #008000;">&#40;</span>vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> <span style="color: #000040;">&amp;</span> V, <span style="color: #0000ff;">const</span> Edge<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> e.<span style="color: #007788;">from</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #008080;">;</span> V<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><span style="color: #008000;">&#41;</span> i <span style="color: #000080;">=</span> V<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 寻找根节点</span>
	<span style="color: #0000ff;">int</span> j <span style="color: #000080;">=</span> e.<span style="color: #007788;">to</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #008080;">;</span> V<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span> <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><span style="color: #008000;">&#41;</span> j <span style="color: #000080;">=</span> V<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 寻找根节点</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>i <span style="color: #000080;">==</span> j<span style="color: #008000;">&#41;</span>	<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ i,j两节点已经联通</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>V<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">&gt;</span> V<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 将小集合合并至大集合上</span>
		V<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> j<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">else</span>
		V<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ ^_^</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/kruskal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio中的Functional</title>
		<link>http://www.dutor.net/index.php/2010/04/visual-studio-functional/</link>
		<comments>http://www.dutor.net/index.php/2010/04/visual-studio-functional/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 09:04:46 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[麻烦]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2149</guid>
		<description><![CDATA[　　今天在VS中遇到一个十分诡异的事情，先看下面这个简单的程序：
<pre lang="cpp" line="1">
class cmp
{
public:
	bool operator()(long long l, long long r)
	{
		//~ 此间内容可略去不看。
		//~ 如果l和r含有的digits完全相同则返回false,
		//~ 如125 vs. 512
		char tmp1[1024], tmp2[1024];
		sprintf(tmp1,"%ld",l);
		sprintf(tmp2,"%ld",r);
		sort(tmp1, tmp1+strlen(tmp1));
		sort(tmp2, tmp2+strlen(tmp2));
		if (!strcmp(tmp1, tmp2))
		{
			return false;
		}
		return true;
	}
};
</pre>
]]></description>
			<content:encoded><![CDATA[<p>　　今天在VS中遇到一个十分诡异的事情，先看下面这个简单的程序：</p>

<div class="wp_codebox"><table><tr id="p214948"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2149code48"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;set&gt;</span>
<span style="color: #339900;">#include &lt;algorithm&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> cmp
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> l, <span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> r<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">//~ 此间内容可略去不看。</span>
		<span style="color: #666666;">//~ 如果l和r含有的digits完全相同则返回false,</span>
		<span style="color: #666666;">//~ 如125 vs. 512</span>
		<span style="color: #0000ff;">char</span> tmp1<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span>, tmp2<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">1024</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>tmp1,<span style="color: #FF0000;">&quot;%ld&quot;</span>,l<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>tmp2,<span style="color: #FF0000;">&quot;%ld&quot;</span>,r<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		sort<span style="color: #008000;">&#40;</span>tmp1, tmp1<span style="color: #000040;">+</span><span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>tmp1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		sort<span style="color: #008000;">&#40;</span>tmp2, tmp2<span style="color: #000040;">+</span><span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span><span style="color: #0000dd;">strcmp</span><span style="color: #008000;">&#40;</span>tmp1, tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	set<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span>,cmp <span style="color: #000080;">&gt;</span> Set<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> a<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">15</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
	Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	Set.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">//~ 此处疯狂</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　程序在这个地方跑偏了，弹出这么个东西</p>
<p><a href="http://www.dutor.net/index.php/2010/04/visual-studio-functional/vsnaocan/" rel="attachment wp-att-2150"><img src="http://www.dutor.net/wp-content/uploads/2010/04/vsnaocan.jpg" alt="" title="vsnaocan" width="377" height="244" class="aligncenter size-full wp-image-2150" /></a><br />
　　可是set的key_compare我一直都是这么用的啊。把程序拷到Linux下面用g++就一切正常。望达人指教。</p>
<h4>更新</h4>
<p>　　Johnny同学给的贴文中提到了，一个predicate对于任两个参数a,b不能返回<strong>两个true</strong>，即pred(a, b)和pred(b, a)不能同时返回true，这是strict weak规则决定的。代码为证：</p>

<div class="wp_codebox"><table><tr id="p214949"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2149code49"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> _Pr, <span style="color: #0000ff;">class</span> _Ty1, <span style="color: #0000ff;">class</span> _Ty2<span style="color: #000080;">&gt;</span> <span style="color: #0000ff;">inline</span>
    <span style="color: #0000ff;">bool</span> __CLRCALL_OR_CDECL _Debug_lt_pred<span style="color: #008000;">&#40;</span>_Pr _Pred, _Ty1<span style="color: #000040;">&amp;</span> _Left, _Ty2<span style="color: #000040;">&amp;</span> _Right,
        <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">wchar_t</span> <span style="color: #000040;">*</span>_Where, <span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">int</span> _Line<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>    <span style="color: #666666;">// test if _Pred(_Left, _Right)  and _Pred is strict weak ordering</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>_Pred <span style="color: #008000;">&#40;</span>_Left, _Right<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>_Pred<span style="color: #008000;">&#40;</span>_Right, _Left<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
        _DEBUG_ERROR2<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;invalid operator&lt;&quot;</span>, _Where, _Line<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　即是说，在调试时（特指Visual Studio的debug模式），bool _Debug_lt_pred()模板函数会对pred(a, b)的返回结果进行检查。如果pred(a, b)返回false没有问题。但如果其返回true，那么_Debug_lt_pred还会对pred(b, a)进行检查，若也返回true就会触发assert（有上图为证）。<br />
　　对于本文最初的代码，为了通过的_Debug_lt_pred的检查，我可以：</p>

<div class="wp_codebox"><table><tr id="p214950"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code" id="p2149code50"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> cmp
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">bool</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> l, <span style="color: #0000ff;">long</span> <span style="color: #0000ff;">long</span> r<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">//~ ……</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span><span style="color: #0000dd;">strcmp</span><span style="color: #008000;">&#40;</span>tmp1, tmp2<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">else</span>
		        <span style="color: #0000ff;">return</span> l <span style="color: #000080;">&lt;</span> r<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>这样就保证了cmp::(long long, long long)不会返回<strong>&#8220;两个true&#8221;</strong>了</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/visual-studio-functional/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[算法]物不知数 &#8211; 中国剩余定理</title>
		<link>http://www.dutor.net/index.php/2010/04/chinese-remainder-theorem/</link>
		<comments>http://www.dutor.net/index.php/2010/04/chinese-remainder-theorem/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 11:59:12 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[数理空间]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[数论]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2142</guid>
		<description><![CDATA[　　设"此物"为x，则x满足同余方程组：
$$\left\{\begin{array}{c}x\equiv 2 (\mod 3)\\x\equiv 3 (\mod 5) \\x\equiv 2 (\mod 7)\end{array}\right.$$
　　若存在x满足上述方程组，则$$x + k*3*5*7$$也满足该方程其中k任意整数，方程的最小正整数解满足$$x\mod{3*5*7}$$，即对3,5,7的最小公倍数求余。
　　在介绍求x的具体方法之前，先介绍两个简单的定理(证明从略)：
<ol>
	<li>被除数增加(或减少)除数的倍数，除数不变，则余数电不变；</li>
	<li>被除数扩大(或缩小)指定的倍数，除数不变，则余数扩大(或缩小)同样的倍数(余数总小于除数)。</li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>　　《孙子算经》有云：</p>
<pre>
今有物不知其数，三三数之剩二；五五数之剩三；七七数之剩二。问物几何？
答曰：二十三。
</pre>
<p>　　设&#8221;此物&#8221;为x，则x满足同余方程组：<br />
<img src="http://www.dutor.net/wp-content/cache/c7e779c7b74e63ffc742866fa2b99510.png" align="absmiddle" class="tex" alt="\left\{\begin{array}{c}x\equiv 2 (\mod 3)\\x\equiv 3 (\mod 5) \\x\equiv 2 (\mod 7)\end{array}\right." /><br />
　　若存在x满足上述方程组，则<img src="http://www.dutor.net/wp-content/cache/8a2a3c9318a9a6e904932054adbd4f14.png" align="absmiddle" class="tex" alt="x + k*3*5*7" />也满足该方程其中k任意整数，方程的最小正整数解满足<img src="http://www.dutor.net/wp-content/cache/8c2b3033dca78fa829cff17821a71eee.png" align="absmiddle" class="tex" alt="x\mod{3*5*7}" />，即对3,5,7的最小公倍数求余。<br />
　　在介绍求x的具体方法之前，先介绍两个简单的定理(证明从略)：</p>
<ol>
<li>被除数增加(或减少)除数的倍数，除数不变，则余数电不变；</li>
<li>被除数扩大(或缩小)指定的倍数，除数不变，则余数扩大(或缩小)同样的倍数(余数总小于除数)。</li>
</ol>
<p>　　接下来，我们这样构造满足条件的x：x由三项相加得出，其中第一项是5和7的倍数且被3除余2，第二项是3和7的倍数且被5除余3，第三项是3和5的倍数且被7除余2。即<img src="http://www.dutor.net/wp-content/cache/f106f29c5644b870bf443626003ff942.png" align="absmiddle" class="tex" alt="x=5*7*p+3*7*q+3*5*t.(p,q,t\in \mathbf{Z})" />。又由于：<br />
<img src="http://www.dutor.net/wp-content/cache/504f4c92e2d7e0d13bf2882c9bad3507.png" align="absmiddle" class="tex" alt="5*7\equiv 2(\mod 3)." />所以<img src="http://www.dutor.net/wp-content/cache/4e6408c808a43d8105daea6152b89f7c.png" align="absmiddle" class="tex" alt="5*7*2\equiv 1 (\mod 3)" />，于是<img src="http://www.dutor.net/wp-content/cache/3b71ee4f6c05a0c2f055f3dce2703ca5.png" align="absmiddle" class="tex" alt="5*7*2*2\equiv 2 (\mod 3)" />;<br />
<img src="http://www.dutor.net/wp-content/cache/a51bff5eaa38cebf222c08970be66408.png" align="absmiddle" class="tex" alt="3*7\equiv 1(\mod 5)." />所以<img src="http://www.dutor.net/wp-content/cache/1d8c5e9a58b24e3e1fcaf0007cdf9125.png" align="absmiddle" class="tex" alt="3*7*3\equiv 3 (\mod 5)" />;<br />
<img src="http://www.dutor.net/wp-content/cache/d092a38f64ca373a37ed616e8736d469.png" align="absmiddle" class="tex" alt="3*5\equiv 1(\mod 7)." />所以<img src="http://www.dutor.net/wp-content/cache/c815addce2bb6b40506da3145f94d072.png" align="absmiddle" class="tex" alt="3*5*2\equiv 2 (\mod 7)" />.<br />
最后，<img src="http://www.dutor.net/wp-content/cache/4a482446738fe8ddd85cab816fffdb5c.png" align="absmiddle" class="tex" alt="x=5*7*2*2+3*7*3+3*5*2=233\equiv 23 (\mod 105)." /><br />
反复观察上述构造过程，我们就不难从中找出规律，而这个规律就是下面要介绍的中国剩余定理，又称孙子定理。它说的是，设<img src="http://www.dutor.net/wp-content/cache/9a54e2e19c6992b85cb5e13987aad16d.png" align="absmiddle" class="tex" alt="n\ge2, a_1,a_2,\ldots,a_n" />为互质整数。<img src="http://www.dutor.net/wp-content/cache/5970623c0f45bff29f5970246bc583ce.png" align="absmiddle" class="tex" alt="M=a_1\cdot a_2 \cdots a_n" />为最小公倍数。又有关于W的同余方程组如下：<br />
<img src="http://www.dutor.net/wp-content/cache/c3fa14987e9aff138a9abb1d230c970e.png" align="absmiddle" class="tex" alt="\left\{\begin{array}{l}W\equiv r_1 (\mod a_1)\\W\equiv r_2 (\mod a_2)\\\vdots\\W\equiv r_n (\mod a_n)\end{array}\right." /><br />
该方程组有且仅有解<br />
<img src="http://www.dutor.net/wp-content/cache/96f39e157e521ea275c540893fc31ceb.png" align="absmiddle" class="tex" alt="W=M_1\cdot\alpha_1\cdot r_1 + M_2\cdot\alpha_2\cdot r_2+\cdots+M_n\cdot\alpha_n\cdot r_n" /><br />
其中，<img src="http://www.dutor.net/wp-content/cache/d27ab0ee57028c06ead943c00cb5b0da.png" align="absmiddle" class="tex" alt="M_i=a_1\cdot a_2\cdots a_{i-1}\cdot a_{i+1}\cdots a_n" /><br />
<img src="http://www.dutor.net/wp-content/cache/cd0f1069db14b3485b705eb04d3e58a4.png" align="absmiddle" class="tex" alt="\alpha_i" />为调整因子，使得<img src="http://www.dutor.net/wp-content/cache/782c4384dcc5cfe22aa23150d87040cc.png" align="absmiddle" class="tex" alt="M_i\cdot\alpha_i\equiv 1(\mod a_i)" />。</p>
<p>over~</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/chinese-remainder-theorem/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[C++]函数调用与变量定义的二义性</title>
		<link>http://www.dutor.net/index.php/2010/04/func-dec-arbitrary/</link>
		<comments>http://www.dutor.net/index.php/2010/04/func-dec-arbitrary/#comments</comments>
		<pubDate>Sat, 10 Apr 2010 07:26:05 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之算法神奇]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2133</guid>
		<description><![CDATA[　　首先，你知道下面的语句的语义是什么吗？
<pre lang="c">
int (a);
</pre>
或许写成这样你会更明白一点：
<pre lang="c">
int (a) = 0;
</pre>
它等同于
<pre lang="c">
int a = 0;
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　首先，你知道下面的语句的语义是什么吗？</p>

<div class="wp_codebox"><table><tr id="p213351"><td class="code" id="p2133code51"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>或许写成这样你会更明白一点：</p>

<div class="wp_codebox"><table><tr id="p213352"><td class="code" id="p2133code52"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> <span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>它等同于</p>

<div class="wp_codebox"><table><tr id="p213353"><td class="code" id="p2133code53"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> a <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>即，在C/C++中，声明变量时允许你在变量名周围加上一对()。这样，我们的问题就来了。看下面这个奇怪的snippet:</p>

<div class="wp_codebox"><table><tr id="p213354"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code" id="p2133code54"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> G <span style="color: #000080;">=</span> <span style="color: #208080;">0xFF</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Mary
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    Mary<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        Mary<span style="color: #008000;">&#40;</span>G<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    Mary<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #ff0000; font-style: italic;">/*Constructing... */</span><span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Mary M<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　这个程序有什么问题？看似很正常。在Mary::Mary()中调用Mary::Mary(int)，让Mary::Mary(int)进行构造工作。编译运行这个程序，你会得到Segment fault的错误。为什么？因为编译器将语句Mary(G); 当成变量定义来编译了。结果就是，Mary::Mary()会被无穷递归地调用，最终造成栈溢出。如果将Mary(G);改成Mary::Mary(G);呢？这样不但无济于事，而且恰恰更具有迷惑性。<br />
　　解决方法就是，通知编译器，这不是一般的变量定义，而是一个函数调用。比如把Mary(G)换成Mary(static_cast&lt;int>G);这样编译器就不会&#8221;神经质&#8221;地一通递归了。<br />
　　<strong>当变量的定义和函数的调用产生二义性时，编译器默认的行为是将其当成变量的定义来解释。</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/04/func-dec-arbitrary/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>标准库 &amp; 系统调用 &amp; 缓冲</title>
		<link>http://www.dutor.net/index.php/2010/03/c-syscall-buffer/</link>
		<comments>http://www.dutor.net/index.php/2010/03/c-syscall-buffer/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 00:46:58 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[边走编程]]></category>
		<category><![CDATA[OS基础]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2108</guid>
		<description><![CDATA[　　本文通过一个文件拷贝程序的三个不同实现，来说明标准库fread/fwrite、系统调用read/write在缓冲机制上的不同。系统调用没有缓冲(这里不考虑内核缓冲)，拿write来说，它的原型int write(int fd, char *buf, size)。write将buf处的size个字节立即写入文件描述符fd指名的文件，而不经过任何缓冲。而C标准库中的f系列函数(fwrite/fread/fgetc/fputc)在FILE结构中内部维护了一个缓冲区(大小是多少？)，通常情况下只有当这个缓冲区被写满时才会调用write将其真正地写入文件，fflush(FILE* stream)会强制将缓冲区内容写出。
<pre lang="c" line="1">
int
main (int argc, char **argv)
{
    int c; //~ fgetc()返回int
    FILE* fdin = fopen("51.tar.gz", "r");
    FILE* fdout = fopen("51.tar.gz.bak", "w");
    if (!fdout &#124;&#124; !fdin)
    {
        fprintf(stderr, "open failure\n");
        exit(1);
    }
    while ((c = fgetc(fdin)) != EOF)
    {
        fputc(c, fdout);
    }
    fclose(fdout);
    fclose(fdin);
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　本文通过一个文件拷贝程序的三个不同实现，来说明标准库fread/fwrite、系统调用read/write在缓冲机制上的不同。系统调用没有缓冲(这里不考虑内核缓冲)，拿write来说，它的原型int write(int fd, char *buf, size)。write将buf处的size个字节立即写入文件描述符fd指名的文件，而不经过任何缓冲。而C标准库中的f系列函数(fwrite/fread/fgetc/fputc)在FILE结构中内部维护了一个缓冲区(大小是多少？)，通常情况下只有当这个缓冲区被写满时才会调用write将其真正地写入文件，fflush(FILE* stream)会强制将缓冲区内容写出。<br />
　　<br />
　　首先是一个使用系统调用，逐字节的将文件51.tar.gz(113M)拷贝到51.tar.gz.bak：</p>

<div class="wp_codebox"><table><tr id="p210855"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2108code55"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
<span style="color: #339933;">#include &lt;unistd.h&gt;</span>
<span style="color: #339933;">#include &lt;fcntl.h&gt;</span>
<span style="color: #339933;">#include &lt;sys/types.h&gt;</span>
<span style="color: #339933;">#include &lt;sys/stat.h&gt;</span>
<span style="color: #993333;">int</span>
main <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> N <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #666666; font-style: italic;">//~const int N = 4096;</span>
    <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span>N<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> fdin <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;51.tar.gz&quot;</span><span style="color: #339933;">,</span> O_RDONLY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> fdout <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;51.tar.gz.bak&quot;</span><span style="color: #339933;">,</span> O_WRONLY<span style="color: #339933;">|</span>O_CREAT<span style="color: #339933;">|</span>O_TRUNC<span style="color: #339933;">,</span> S_IRWXU<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fdout <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span> <span style="color: #339933;">||</span> fdin <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        fprintf<span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;open failure<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #993333;">int</span> count<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>count <span style="color: #339933;">=</span> read<span style="color: #009900;">&#40;</span>fdin<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        write<span style="color: #009900;">&#40;</span>fdout<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> count<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    close<span style="color: #009900;">&#40;</span>fdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    close<span style="color: #009900;">&#40;</span>fdin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>所用时间：</p>
<pre>
real    16m26.801s
user    0m28.686s
sys     15m50.243s
</pre>
<p>第二个程序(改变const int N的大小)，还是利用系统调用，但却是4K为单位拷贝，用时</p>
<pre>
real    0m0.470s
user    0m0.012s
sys     0m0.460s
</pre>
<p>第三个程序，使用fgetc/fputc来逐字节拷贝：</p>

<div class="wp_codebox"><table><tr id="p210856"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p2108code56"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span>
main <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> c<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//~ fgetc()返回int</span>
    FILE<span style="color: #339933;">*</span> fdin <span style="color: #339933;">=</span> fopen<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;51.tar.gz&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;r&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    FILE<span style="color: #339933;">*</span> fdout <span style="color: #339933;">=</span> fopen<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;51.tar.gz.bak&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;w&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>fdout <span style="color: #339933;">||</span> <span style="color: #339933;">!</span>fdin<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        fprintf<span style="color: #009900;">&#40;</span>stderr<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;open failure<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        exit<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>c <span style="color: #339933;">=</span> fgetc<span style="color: #009900;">&#40;</span>fdin<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> EOF<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        fputc<span style="color: #009900;">&#40;</span>c<span style="color: #339933;">,</span> fdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    fclose<span style="color: #009900;">&#40;</span>fdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fclose<span style="color: #009900;">&#40;</span>fdin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>用时</p>
<pre>
real    0m4.602s
user    0m4.192s
sys     0m0.408s
</pre>
<h4>简要的分析</h4>
<p>　　第一个程序用时十多分钟！我们知道系统调用要陷入内核，比较耗时，113M的文件大约需要1亿次调用read和write，反复频繁地陷入内核，当然会非常慢。<br />
　　第二个程序拷贝文件用了不到半秒钟，它一次从源文件中读取4K，然后再一次写入目标文件，系统调用次数不到3万次，大大缩减了陷入内核过程所占用的时间，拷贝过程就快了很多。<br />
　　再说第三个程序，由于标准库为进程维护着一个自己缓冲区，除非显式刷新，否则只有当缓冲区被写满时才会调用write将缓冲数据写出，因此系统调用的次数也很少。为什么比第二个程序慢呢？一来，标准的缓冲区可能不是4K，更重要的是fgetc/fputc是一个函数，会被调用上亿次，虽说在用户空间执行，但毕竟是函数调用，还是会占用相当一部分的时间。<br />
　　如果有兴趣，你可以用fread/fwrite来重写这个拷贝程序，相比第三个程序，性能肯定还会有不小的提升。</p>
<h4>小疑问</h4>
<p>　　fgetc的原型：int fgetc(FILE* stream). 上面第三个程序中，如果把int c换成char c就会出问题，文件被拷贝128字节就over了～～～这是咋回事？<br />
　　仔细分析一下，</p>

<div class="wp_codebox"><table><tr id="p210857"><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code" id="p2108code57"><pre class="c" style="font-family:monospace;">    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>c <span style="color: #339933;">=</span> fgetc<span style="color: #009900;">&#40;</span>fdin<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> EOF<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        fputc<span style="color: #009900;">&#40;</span>c<span style="color: #339933;">,</span> fdout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>fgetc()返回的是int，付给char c时会转换为char(singed or unsigned? )，就会有数据截断，又由于EOF会被多数编译器定义为int型的-1，因此char c在与int EOF比较时会被提升为int。在这两次转换过程中，fgetc原本的返回值就有可能被篡改。也就有可能出现非EOF被解释为EOF的情况：</p>
<table>
<caption>signed char的情况</caption>
<tr>
<th>int fgetc()</th>
<th>signed char</th>
<th>converted int fgetc()</th>
</tr>
<tr>
<td>00 xx xx FF</td>
<td>FF</td>
<td>FF FF FF FF</td>
</tr>
</table>
<table>
<caption>unsigned char的情况</caption>
<tr>
<th>int fgetc()</th>
<th>unsigned char</th>
<th>converted int fgetc()</th>
</tr>
<tr>
<td>00 xx xx FF</td>
<td>FF</td>
<td>00 00 00 FF</td>
</tr>
</table>
<p>可以看出，在signed char的情况下，转型后的非EOF有可能会被错当作EOF。<br />
　　此外，还有，<font style="color:#FF9900;">int getc(FILE*)/int getchar(), int fputc(int, FILE*)/int putc(FILE*)/int putchar(int)</font>等，用时谨慎。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/c-syscall-buffer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[C++]优先级队列priority_queque</title>
		<link>http://www.dutor.net/index.php/2010/03/priority_queque/</link>
		<comments>http://www.dutor.net/index.php/2010/03/priority_queque/#comments</comments>
		<pubDate>Sat, 27 Mar 2010 11:15:59 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[STL]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2096</guid>
		<description><![CDATA[　　好久没写C++没用STL了，今天在STLChina泡了一下午。完整的代码只写了这么一个，贴上来吧。
　　写了两个类，Max_Heap和Min_Heap，以他们特例化priority_queue，可以方便地实现最大、最小堆。写完了忽然又觉得这俩类似乎是多此一举了，完全可以用greater<int>来实现最小堆，但由priority_queue的模板定义看出，那样就必须提供一个容器类型，比如vector<int>。
　　最后还写了测试用例：找出ｎ个数中最大的k个。
<pre lang="cpp" line="1">
/*
template < class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type> > class priority_queue;

explicit priority_queue ( const Compare&#038; x = Compare(),
                          const Container&#038; y = Container() );
template <class InputIterator>
         priority_queue ( InputIterator first, InputIterator last,
                          const Compare&#038; x = Compare(),
                          const Container&#038; y = Container() );
*/
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　好久没写C++没用STL了，今天在STLChina泡了一下午。完整的代码只写了这么一个，贴上来吧。<br />
　　写了两个类，Max_Heap和Min_Heap，以他们特例化priority_queue，可以方便地实现最大、最小堆。写完了忽然又觉得这俩类似乎是多此一举了，完全可以用greater<int>来实现最小堆，但由priority_queue的模板定义看出，那样就必须提供一个容器类型，比如vector<int>。<br />
　　最后还写了测试用例：找出ｎ个数中最大的k个。</p>

<div class="wp_codebox"><table><tr id="p209658"><td class="line_numbers"><pre>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
</pre></td><td class="code" id="p2096code58"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*
template &lt; class T, class Container = vector&lt;T&gt;,
           class Compare = less&lt;typename Container::value_type&gt; &gt; class priority_queue;
&nbsp;
explicit priority_queue ( const Compare&amp; x = Compare(),
                          const Container&amp; y = Container() );
template &lt;class InputIterator&gt;
         priority_queue ( InputIterator first, InputIterator last,
                          const Compare&amp; x = Compare(),
                          const Container&amp; y = Container() );
*/</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;queue&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Max_Heap
<span style="color: #008000;">&#123;</span>
    Max_Heap<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> _n<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> _n<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span> <span style="color: #666666;">//在需要的地方隐式类型转换</span>
    <span style="color: #0000ff;">int</span> _n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Min_Heap
<span style="color: #008000;">&#123;</span>
    Min_Heap<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> n<span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span> _n<span style="color: #008000;">&#40;</span>n<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
    operator <span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> _n<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span> <span style="color: #666666;">//在需要的地方隐式类型转换</span>
    <span style="color: #0000ff;">int</span> _n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">bool</span> operator <span style="color: #000080;">&lt;</span> <span style="color: #008000;">&#40;</span>Max_Heap l, Max_Heap r<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 正常的&lt;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l._n <span style="color: #000080;">&lt;</span> r._n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> operator <span style="color: #000080;">&lt;</span> <span style="color: #008000;">&#40;</span>Min_Heap l, Min_Heap r<span style="color: #008000;">&#41;</span> <span style="color: #666666;">//~ 反义的&lt;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> l._n <span style="color: #000080;">&gt;</span> r._n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span>
main <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    priority_queue<span style="color: #000080;">&lt;</span>Min_Heap<span style="color: #000080;">&gt;</span> heap<span style="color: #008080;">;</span> <span style="color: #666666;">//~ 最小堆</span>
    <span style="color: #666666;">//priority_queue&lt;Max_Heap&gt; heap; //~ 最大堆</span>
    <span style="color: #666666;">//~ 测试用例</span>
    <span style="color: #666666;">//~ 前K个最大值</span>
    <span style="color: #0000ff;">int</span> k <span style="color: #000080;">=</span> <span style="color: #0000dd;">5</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> tmp<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> k<span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>tmp<span style="color: #008080;">;</span>
        heap.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>tmp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">cin</span><span style="color: #000080;">&gt;&gt;</span>tmp<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>tmp <span style="color: #000080;">&gt;</span> heap.<span style="color: #007788;">top</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>._n<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            heap.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>tmp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            heap.<span style="color: #007788;">pop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000dd;">cin</span>.<span style="color: #007788;">clear</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>heap.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>heap.<span style="color: #007788;">top</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>._n<span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">' '</span><span style="color: #008080;">;</span>
        heap.<span style="color: #007788;">pop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/priority_queque/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个关于大小端的问题</title>
		<link>http://www.dutor.net/index.php/2010/03/big-little-endian/</link>
		<comments>http://www.dutor.net/index.php/2010/03/big-little-endian/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 09:14:59 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[大小端]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2015</guid>
		<description><![CDATA[　　所谓大小端模式，就是一个关于数据字节在存储顺序的问题。在某些编程环境中，了解大小端是非常重要的，比如汇编和网络编程中，对存取和发送、接收数据的字节序都有严格的要求。当然，在高层次，你很少会需要考虑到这些。为什么会有大小端模式之分呢？这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节。在许多计算机语言中，许多数据类型都是多字节的，这就产生了多字节数据在内存中存放数据的问题。在大端模式（Big-endian）中，数据的低位（就是权值较小的后面那几位）保存在内存的高地址中，而数据的高位，保存在内存的低地址中；在小端模式（Little-endian）中，数据低位就存放在内存的低位。了解了什么是大小端，看下面的程序，输出结果是什么？
<pre lang="c" line="1">
#include <stdio.h>
int
main()
{
    int a[] = {1, 2, 3, 4, 5};
    int *ptr1 = (int*) (&#038;a + 1) - 1;
    int *ptr2 = (int*) ((int)a + 1);
    printf("%x, %x\n", *ptr1, *ptr2);
    return 0;
}
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　所谓大小端模式，就是一个关于数据字节在存储顺序的问题。在某些编程环境中，了解大小端是非常重要的，比如汇编和网络编程中，对存取和发送、接收数据的字节序都有严格的要求。当然，在高层次，你很少会需要考虑到这些。为什么会有大小端模式之分呢？这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节。在许多计算机语言中，许多数据类型都是多字节的，这就产生了多字节数据在内存中存放数据的问题。在大端模式（Big-endian）中，数据的低位（就是权值较小的后面那几位）保存在内存的高地址中，而数据的高位，保存在内存的低地址中；在小端模式（Little-endian）中，数据低位就存放在内存的低位。了解了什么是大小端，看下面的程序，输出结果是什么？</p>

<div class="wp_codebox"><table><tr id="p201559"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p2015code59"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #993333;">int</span>
main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">5</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>ptr1 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>a <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>ptr2 <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span>a <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%x, %x<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">*</span>ptr1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>ptr2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>　　在我的机器上的输出时5, 2000000，可以看出是处理器是小端模式的。为什么呢？<br />
　　首先*ptr1 == 5是没有疑问的。<br />
　　再看看，*ptr2：</p>
<table>
<tr>
<td>内存编号</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>……</td>
</tr>
<tr>
<td>数据内容(16进制)</td>
<td>0&#215;01</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;02</td>
<td>……</td>
</tr>
</table>
<p>　　指针ptr2指向1号单元，因此*ptr2就是0&#215;02000000。在大端模式的机器中内存布局应该是这样滴：</p>
<table>
<tr>
<td>内存编号</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>……</td>
</tr>
<tr>
<td>数据内容(16进制)</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;00</td>
<td>0&#215;01</td>
<td>0&#215;00</td>
<td>……</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/big-little-endian/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>[C++]虚 静态函数</title>
		<link>http://www.dutor.net/index.php/2010/03/virtual-static-function/</link>
		<comments>http://www.dutor.net/index.php/2010/03/virtual-static-function/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 10:44:28 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=2012</guid>
		<description><![CDATA[　　C++类的静态函数是属于类型的，而不是某个对象的，因此把它声明成Virtual也没什么实际意义。那么运行下面这段程序，会产生什么样的结果呢？
<pre lang="cpp" line="1">
#include <iostream>
using namespace std;
class Base
{
public:
    static void foo() { cout<<"Base"<<endl; }
    virtual void bar() { foo(); }
};
</pre>]]></description>
			<content:encoded><![CDATA[<p>　　C++类的静态函数是属于类型的，而不是某个对象的，因此把它声明成Virtual也没什么实际意义。那么运行下面这段程序，会产生什么样的结果呢？</p>

<div class="wp_codebox"><table><tr id="p201260"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code" id="p2012code60"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Base
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Base&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">class</span> Derived<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Base
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span><span style="color: #FF0000;">&quot;Derived&quot;</span><span style="color: #000080;">&lt;&lt;</span>endl<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main
<span style="color: #008000;">&#123;</span>
    Base <span style="color: #000040;">*</span> p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Derived<span style="color: #008080;">;</span>
    p<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>bar<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000dd;">delete</span> p<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/03/virtual-static-function/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>[Tricks]C++成员函数和静态变量</title>
		<link>http://www.dutor.net/index.php/2010/02/cpp-fun-st/</link>
		<comments>http://www.dutor.net/index.php/2010/02/cpp-fun-st/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 15:34:18 +0000</pubDate>
		<dc:creator>dutor</dc:creator>
				<category><![CDATA[之语言特性]]></category>
		<category><![CDATA[边走编程]]></category>
		<category><![CDATA[Cpp]]></category>

		<guid isPermaLink="false">http://www.dutor.net/?p=1989</guid>
		<description><![CDATA[　　想一下，下面的代码片段会输出什么？
<pre lang="cpp" line="1">
#include <iostream>
class Test
{
public:
    void print() const
    {
        std::cout<<_int<<std::endl;
    }
private:
    static int _int;
};
int Test::_int = 0;
int
main(int argc, char **argv)
{
    Test TArray[10];
    TArray[100].print();
    return 0;
}
</pre>
　　May you note something, anyhow.]]></description>
			<content:encoded><![CDATA[<p>　　想一下，下面的代码片段会输出什么？</p>

<div class="wp_codebox"><table><tr id="p198961"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code" id="p1989code61"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #0000ff;">class</span> Test
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> print<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">const</span>
    <span style="color: #008000;">&#123;</span>
        std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #000080;">&lt;&lt;</span>_int<span style="color: #000080;">&lt;&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> _int<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> Test<span style="color: #008080;">::</span>_int <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span>
main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span> <span style="color: #000040;">**</span>argv<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Test TArray<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">10</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
    TArray<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">print</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>　　May you note something, anyhow.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dutor.net/index.php/2010/02/cpp-fun-st/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>