<?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>Личный опыт разработки ПО</title>
	<atom:link href="http://www.devexp.ru/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.devexp.ru</link>
	<description>Сборник рецептов</description>
	<lastBuildDate>Mon, 07 Oct 2024 16:12:11 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.6.29</generator>

<image>
	<url>http://www.devexp.ru/wp-content/uploads/2016/12/cropped-no_bug_1-32x32.jpg</url>
	<title>Личный опыт разработки ПО</title>
	<link>http://www.devexp.ru</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Автоматическое добавление версии билда в код с помощью CMake</title>
		<link>http://www.devexp.ru/2012/06/avtomaticheskoe-dobavlenie-versii-bilda-v-kod-s-pomoshhyu-cmake/</link>
		<comments>http://www.devexp.ru/2012/06/avtomaticheskoe-dobavlenie-versii-bilda-v-kod-s-pomoshhyu-cmake/#comments</comments>
		<pubDate>Sat, 23 Jun 2012 12:31:54 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CMake]]></category>
		<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Сборка]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2012/06/avtomaticheskoe-dobavlenie-versii-bilda-v-kod-s-pomoshhyu-cmake/</guid>
		<description><![CDATA[Очень удобно всегда знать какой конкретно версии та или иная сборка проекта. Для этого обычно вводят номер версии, состоящий из нескольких цифр. Я являюсь сторонником структуры состоящей из 4 цифр, вида: Именование Смысл Major Изменение этого поля указывает на то, что изменения функционала весьма существенные. Возможно даже была утрачена совместимость по файлам данных и протоколам. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Очень удобно всегда знать какой конкретно версии та или иная сборка проекта. Для этого обычно вводят номер версии, состоящий из нескольких цифр. Я являюсь сторонником структуры состоящей из 4 цифр, вида:</p>
<table border="1" cellspacing="0" cellpadding="2" width="100%">
<tbody>
<tr>
<td valign="top"><strong>Именование</strong></td>
<td valign="top"><strong>Смысл</strong></td>
</tr>
<tr>
<td valign="top">Major</td>
<td valign="top">Изменение этого поля указывает на то, что изменения функционала весьма существенные. Возможно даже была утрачена совместимость по файлам данных и протоколам.</td>
</tr>
<tr>
<td valign="top">Minor</td>
<td valign="top">Указывает, что версия с большим значением этого поля, обладает большим функционалом.</td>
</tr>
<tr>
<td valign="top">Patch</td>
<td valign="top">Значение изменяется при выпуске новых версий, которые содержат исправления.</td>
</tr>
<tr>
<td valign="top">Build</td>
<td valign="top">Удобно для внутреннего использования, чтобы ссылаться на одну и ту же версию кода.</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p>Все вместе это и формирует полное именование версии (Major.Minor.Pathch.Build):</p>
<p>4.6.12.589</p>
<p>Некоторые используют в качестве build уникальное числовое значение, которое увеличивается каждый раз, например, при ночной сборке. Я считаю, что никакого смысла в этом нет – гораздо удобнее привязать данный номер к ревизии в репозитории. Я использую Subversion и CMake, поэтому продемонстрирую как можно автоматизировать проставлении версии билда с этими инструментами.</p>
<p>  <span id="more-85"></span>
<p>Первое – необходимо добавить заголовочный файл в проект (например, version.h):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;string&gt;</span>
&nbsp;
<span style="color: #339900;">#include &lt;boost/cstdint.hpp&gt;</span>
&nbsp;
<span style="color: #0000ff;">namespace</span> Version
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> AsText<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint64_t</span> AsNumber<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>
<p>Теперь приведу содержимое version.cpp:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/format.hpp&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;../version.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">namespace</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint8_t</span> MAJOR <span style="color: #000080;">=</span> <span style="color: #0000dd;">4</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint16_t</span> MINOR <span style="color: #000080;">=</span> <span style="color: #0000dd;">6</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint16_t</span> PATCH <span style="color: #000080;">=</span> <span style="color: #0000dd;">12</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint32_t</span> BUILD <span style="color: #000080;">=</span> <span style="color: #0000dd;">589</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Это значение будет изменено автоматически</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> Version<span style="color: #008080;">::</span><span style="color: #007788;">AsText</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> text <span style="color: #000080;">=</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">str</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">format</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%1%.%2%.%3%.%4%&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span>
		<span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">unsigned</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>MAJOR<span style="color: #008000;">&#41;</span> <span style="color: #000040;">%</span> MINOR <span style="color: #000040;">%</span> PATCH <span style="color: #000040;">%</span> BUILD<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">return</span> text<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint64_t</span> Version<span style="color: #008080;">::</span><span style="color: #007788;">AsNumber</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	BOOST_STATIC_ASSERT<span style="color: #008000;">&#40;</span>BUILD <span style="color: #000080;">&lt;</span> <span style="color: #208080;">0xFFFFFF</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> boost<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">size_t</span> size <span style="color: #000080;">=</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">uint64_t</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #0000ff;">uint64_t</span> number <span style="color: #000080;">=</span>
		<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">uint64_t</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>MAJOR<span style="color: #008000;">&#41;</span> 
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #008000;">&#40;</span>size <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>MAJOR<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">8</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">|</span>
		<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">uint64_t</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>MINOR<span style="color: #008000;">&#41;</span> 
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #008000;">&#40;</span>size <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>MAJOR<span style="color: #008000;">&#41;</span> <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>MINOR<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">8</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">|</span>
		<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">static_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">uint64_t</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>PATCH<span style="color: #008000;">&#41;</span> 
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #008000;">&#40;</span>size <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>MAJOR<span style="color: #008000;">&#41;</span> <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>MINOR<span style="color: #008000;">&#41;</span> <span style="color: #000040;">-</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>PATCH<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">8</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">|</span>
		BUILD<span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">return</span> number<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Здесь все тривиально и, думаю, не требует комментариев. Последнее, что осталось – механизм изменения значения BUILD, на номер ревизии в репозитории. С этим отлично справится CMake, просто добавьте в CMakeLists.txt следующий код:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">set</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>VERSION_FILE ..<span style="color: #000000; font-weight: bold;">/</span>common<span style="color: #000000; font-weight: bold;">/</span>sources<span style="color: #000000; font-weight: bold;">/</span>version.cpp<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
find_package <span style="color: #7a0874; font-weight: bold;">&#40;</span>Subversion REQUIRED<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Subversion_WC_INFO <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #800000;">${PROJECT_SOURCE_DIR}</span> Repo<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>READ <span style="color: #800000;">${VERSION_FILE}</span> OLD_CODE<span style="color: #7a0874; font-weight: bold;">&#41;</span>
foreach <span style="color: #7a0874; font-weight: bold;">&#40;</span>LINE <span style="color: #800000;">${OLD_CODE}</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	string <span style="color: #7a0874; font-weight: bold;">&#40;</span>REGEX MATCH <span style="color: #ff0000;">&quot;BUILD = ([0-9]+)&quot;</span> BUILD_NUMBER <span style="color: #800000;">${LINE}</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>BUILD_NUMBER<span style="color: #7a0874; font-weight: bold;">&#41;</span>
		string <span style="color: #7a0874; font-weight: bold;">&#40;</span>REGEX REPLACE <span style="color: #ff0000;">&quot;[0-9]+$&quot;</span> <span style="color: #800000;">${Repo_WC_REVISION}</span> LINE <span style="color: #800000;">${LINE}</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	endif <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>NEW_CODE <span style="color: #800000;">${NEW_CODE}</span> <span style="color: #800000;">${LINE}</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
endforeach <span style="color: #7a0874; font-weight: bold;">&#40;</span>LINE<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>WRITE <span style="color: #800000;">${VERSION_FILE}</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${NEW_CODE}</span>&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></td></tr></table></div>

<p>&#160;</p>
<p>Единственная тонкость в скрипте в последней строке, а конкретней – кавычки в &quot;${NEW_CODE}&quot;, без них будут убраны все “;”.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2012/06/avtomaticheskoe-dobavlenie-versii-bilda-v-kod-s-pomoshhyu-cmake/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>Многопоточность, баги и списки инициализации</title>
		<link>http://www.devexp.ru/2011/11/mnogopotochnost-bagi-i-spiski-inicializacii/</link>
		<comments>http://www.devexp.ru/2011/11/mnogopotochnost-bagi-i-spiski-inicializacii/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 18:38:30 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[Многопоточность]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2011/11/mnogopotochnost-bagi-i-spiski-inicializacii/</guid>
		<description><![CDATA[Разработка многопоточных программ – задача нетривиальная. Локализовать место ошибки сложно, отладка затруднена, иногда даже возникает желание все свалить на ошибки в сторонних библиотеках и/или компилятор/операционную систему. Так делать не надо. Конечно вероятность такая есть, но она несравненно меньше того, что виновником ошибки являетесь именно вы. Например приложение работает хорошо, ну скажем в 95 случаях из [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Разработка многопоточных программ – задача нетривиальная. Локализовать место ошибки сложно, отладка затруднена, иногда даже возникает желание все свалить на ошибки в сторонних библиотеках и/или компилятор/операционную систему. Так делать не надо. Конечно вероятность такая есть, но она несравненно меньше того, что виновником ошибки являетесь именно вы.</p>
<p>Например приложение работает хорошо, ну скажем в 95 случаях из 100, но в оставшихся пяти оно может зависнуть или вылететь с segmentation fault. А может упасть.</p>
<p>Посмотрим на следующий код:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;condition_variable&gt;</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;queue&gt;</span>
<span style="color: #339900;">#include &lt;mutex&gt;</span>
<span style="color: #339900;">#include &lt;thread&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Worker
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    Worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008080;">:</span> shutdown_<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span>
        , thread_<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Worker<span style="color: #008080;">::</span><span style="color: #007788;">taskProcessor</span>, <span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    ~Worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #008000;">&#123;</span>
            std<span style="color: #008080;">::</span><span style="color: #007788;">lock_guard</span><span style="color: #000080;">&lt;</span>decltype<span style="color: #008000;">&#40;</span>mutex_<span style="color: #008000;">&#41;</span><span style="color: #000080;">&gt;</span> lock<span style="color: #008000;">&#40;</span>mutex_<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            shutdown_ <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        hasTask_.<span style="color: #007788;">notify_one</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        thread_.<span style="color: #007788;">join</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> addTask<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> taskId<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #008000;">&#123;</span>
            std<span style="color: #008080;">::</span><span style="color: #007788;">lock_guard</span><span style="color: #000080;">&lt;</span>decltype<span style="color: #008000;">&#40;</span>mutex_<span style="color: #008000;">&#41;</span><span style="color: #000080;">&gt;</span> lock<span style="color: #008000;">&#40;</span>mutex_<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: #FF0000;">&quot;Adding task &quot;</span> <span style="color: #000080;">&lt;&lt;</span> taskId <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
            tasks_.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>taskId<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        hasTask_.<span style="color: #007788;">notify_one</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> taskProcessor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">int</span> task <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
            <span style="color: #008000;">&#123;</span>
                std<span style="color: #008080;">::</span><span style="color: #007788;">unique_lock</span><span style="color: #000080;">&lt;</span>decltype<span style="color: #008000;">&#40;</span>mutex_<span style="color: #008000;">&#41;</span><span style="color: #000080;">&gt;</span> lock<span style="color: #008000;">&#40;</span>mutex_<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
                <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>shutdown_<span style="color: #008000;">&#41;</span>
                    <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
&nbsp;
                <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>tasks_.<span style="color: #007788;">empty</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>
                    hasTask_.<span style="color: #007788;">wait</span><span style="color: #008000;">&#40;</span>lock<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>shutdown_<span style="color: #008000;">&#41;</span>
                        <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
&nbsp;
                task <span style="color: #000080;">=</span> tasks_.<span style="color: #007788;">front</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                tasks_.<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>
&nbsp;
            <span style="color: #666666;">// освободили мютекс, чтобы не блокировать другие потоки и делаем работу</span>
            std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Processing task &quot;</span> <span style="color: #000080;">&lt;&lt;</span> task <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>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">bool</span> shutdown_<span style="color: #008080;">;</span>
&nbsp;
    std<span style="color: #008080;">::</span><span style="color: #007788;">queue</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">int</span><span style="color: #000080;">&gt;</span> tasks_<span style="color: #008080;">;</span>
&nbsp;
    std<span style="color: #008080;">::</span><span style="color: #007788;">thread</span> thread_<span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">mutex</span> mutex_<span style="color: #008080;">;</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">condition_variable</span> hasTask_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</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;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    Worker worker<span style="color: #008080;">;</span>
&nbsp;
    <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;">1</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">6</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        worker.<span style="color: #007788;">addTask</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>
&nbsp;
    <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>Здесь приведен простой класс, объект которого обрабатывает некоторые задачи в параллельном потоке. Из основного потока функцией addTask можно добавить задачу в очередь и известить об этом параллельный поток. Поток проснувшись, возьмет из очереди задачу, обработает ее и если задач больше нет – уснет. В деструкторе, прежде чем объект будет уничтожен происходит ожидание обработки всех задач в очереди.</p>
<p>На первый взгляд все прозрачно, но в некоторых случаях, мы вылетим по ассерту из стандартной библиотеки (и даже можем начать грешить на его разработчиков) или зависнем, но повторюсь – ошибка здесь наша.</p>
<p>Проблема в списке инициализации. Как мы помним, конструирование членов класса происходит в порядке их объявления. В нашем случае сначала будет создан объект типа <strong>std::thread</strong> и только после него <strong>std::mutex</strong>. Если звезды сложатся удачно, то запуск параллельного потока займет некоторое время, за которое в основном потоке будет сконструирован мютекс и программа будет работать. Если со звездами не сложиться, то поток начав работу попробует заблокировать мютекс который еще не сконструирован, со всеми вытекающими. Решение простое, но не самое лучшее, так как делает код хрупким – изменить положение членов в списке инициализации:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">boost<span style="color: #008080;">::</span><span style="color: #007788;">mutex</span> Mutex_<span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #007788;">condition_variable</span> hasTask_<span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #007788;">thread</span> thread_<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Лучше будет разделить конструирование и инициализацию:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Worker
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">static</span> std<span style="color: #008080;">::</span><span style="color: #007788;">unique_ptr</span><span style="color: #000080;">&lt;</span>Worker<span style="color: #000080;">&gt;</span> create<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		std<span style="color: #008080;">::</span><span style="color: #007788;">unique_ptr</span><span style="color: #000080;">&lt;</span>Worker<span style="color: #000080;">&gt;</span> worker<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> Worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		worker<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">return</span> worker<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	...
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	Worker<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> shutdown_<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>
&nbsp;
	<span style="color: #0000ff;">void</span> init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		thread_ <span style="color: #000080;">=</span> std<span style="color: #008080;">::</span><span style="color: #007788;">thread</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Worker<span style="color: #008080;">::</span><span style="color: #007788;">taskProcessor</span>, <span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	...
&nbsp;
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2011/11/mnogopotochnost-bagi-i-spiski-inicializacii/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>C++ 0x == C++ 0xB</title>
		<link>http://www.devexp.ru/2011/03/c-0x-c-0xb/</link>
		<comments>http://www.devexp.ru/2011/03/c-0x-c-0xb/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 11:20:31 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Новости]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2011/03/c-0x-c-0xb/</guid>
		<description><![CDATA[Принят финальный драфт нового стандарта C++.&#160; http://herbsutter.com/2011/03/25/we-have-fdis-trip-report-march-2011-c-standards-meeting/ Ура, товарищи! Update. Собственно сам драфт: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf]]></description>
				<content:encoded><![CDATA[<p>Принят финальный драфт нового стандарта C++.&#160; <a href="http://herbsutter.com/2011/03/25/we-have-fdis-trip-report-march-2011-c-standards-meeting/">http://herbsutter.com/2011/03/25/we-have-fdis-trip-report-march-2011-c-standards-meeting/</a></p>
<p>Ура, товарищи!</p>
<p><strong>Update. </strong>Собственно сам драфт: <a title="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2011/03/c-0x-c-0xb/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Конечные автоматы в C++</title>
		<link>http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/</link>
		<comments>http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 20:05:27 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Алгоритмы]]></category>
		<category><![CDATA[Boost]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/</guid>
		<description><![CDATA[В статье рассмотрены простые конечные автоматы и их реализация на C++ с помощью switch-конструкций, таблиц времени исполнения и библиотеки Boost Statechart. Введение Грубо говоря, конечный автомат (Finite State Machine), глазами пользователя – это черный ящик, в который можно что-то передать и что-то оттуда получить. Это очень удобная абстракция, которая позволяет скрыть сложный алгоритм, кроме того [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>В статье рассмотрены простые конечные автоматы и их реализация на C++ с помощью switch-конструкций, таблиц времени исполнения и библиотеки <a href="http://www.boost.org/doc/libs/1_45_0/libs/statechart/doc/index.html">Boost Statechart</a>.</p>
<h2>Введение</h2>
<p>Грубо говоря, конечный автомат (Finite State Machine), глазами пользователя – это черный ящик, в который можно что-то передать и что-то оттуда получить. Это очень удобная абстракция, которая позволяет скрыть сложный алгоритм, кроме того конечные автоматы очень эффективны.</p>
<p>Конечные автоматы изображают в виде диаграмм состоящих из состояний и переходов. Поясню на простом примере:</p>
<p><img src="http://www.devexp.ru/wp-content/uploads/2011/02/lamp.png" /></p>
<p>Как вы наверное догадались – это диаграмма состояний лампочки. Начальное состояние обозначается черным кружком, переходы стрелками, некоторые стрелки подписаны – это события после которых автомат переходит в другое состояние. Итак, сразу из начального состояния, мы попадаем в состояние <strong>Light Off</strong> – лампа не горит. Если нажать кнопку, то автомат изменит свое состояние и перейдет по стрелке помеченной <strong>Push Button</strong>, в состояние <strong>Light On</strong> – лампа горит. Перейти из этого состояния можно опять же по стрелке, после нажатия кнопки, в состояние <strong>Light Off</strong>.</p>
<p>Также широко используются таблицы переходов:</p>
<table border="1" width="100%">
<tbody>
<tr>
<td><strong>Текущее состояние</strong></td>
<td><strong>Событие</strong></td>
<td><strong>Состояние после перехода</strong></td>
<td><strong>Действие</strong></td>
</tr>
<tr>
<td>Light Off</td>
<td>Push Button</td>
<td>Light On</td>
<td>Загорается лампа</td>
</tr>
<tr>
<td>Light On</td>
<td>Push Button</td>
<td>Light Off</td>
<td>Лампа гаснет</td>
</tr>
</tbody>
</table>
<h2>Практическое применение автоматов</h2>
<p>Конечные автоматы широко используются в программировании. Например очень удобно представить работу устройства в виде автомата. Это сделает код проще и позволит легко с ним экспериментировать и поддерживать.</p>
<p>Также конечные автоматы применяют для написания всевозможных парсеров и анализаторов текста, с помощью них можно эффективно проводить поиск подстрок, регулярные выражения тоже транслируются в конечный автомат.</p>
<p>  <span id="more-78"></span>
<p>Для примера мы реализуем автомат для подсчета чисел и слов в тексте. Для начала договоримся, что числом будет считаться последовательность цифр от 0 до 9 произвольной длины, окруженная пробельными символами (пробел, табуляция, перевод строки). Словом будет считаться последовательность произвольной длины состоящая из букв и также окруженная пробельными символами.</p>
<p>Рассмотрим диаграмму:</p>
<p><img src="http://www.devexp.ru/wp-content/uploads/2011/02/counter.png" /></p>
<p>Из начального состояния мы попадаем в состояние <strong>Start</strong>. Проверяем текущий символ, и если он является буквой, то переходим в состояние <strong>Word </strong>по стрелке помеченной как <strong>Letter</strong>. Это состояние предполагает, что в данный момент мы рассматриваем слово, анализ дальнейших символов, либо подтвердит данное предположение, либо опровергнет. Итак, рассматриваем следующий символ, если он является буквой, то состояние не изменяется (обратите внимание на круговую стрелку помеченную как <strong>Letter</strong>). Если символ не является буквой, а соответствует пробельному символу, то это означает, что предположение было верным и мы обнаружили слово (делаем переход по стрелке <strong>Space</strong> в состояние <strong>Start</strong>). Если символ не является, ни буквой, ни пробелом, значит мы ошиблись в предположении и последовательность которую мы рассматриваем, не является словом (переходим по стрелке <strong>Unknown</strong> в состояние <strong>Skip</strong>).</p>
<p>В состоянии <strong>Skip</strong> мы находимся до тех пор, пока не будет встречен пробельный символ. После того как пробел был обнаружен мы переходим по стрелке <strong>Space</strong> в состояние <strong>Start</strong>. Это нужно, чтобы полностью пропустить строку не соответствующую нашему шаблону поиска.</p>
<p>После перехода в состояние <strong>Start</strong>, поиск цикл повторяется с начала. Ветвь с распознаванием чисел аналогична ветви распознавания слов.</p>
<h2>Автомат с использованием switch-инструкций</h2>
<p>Первое – возможные состояния:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">enum</span> States
<span style="color: #008000;">&#123;</span>
	State_Start,
	State_Number,
	State_Word,
	State_Skip
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Начальное состояние:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">States state <span style="color: #000080;">=</span> State_Start<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>После чего мы итерируем по строке подсовывая автомату текущий символ. Сам автомат представляет собой инструкцию switch сначала выполняющей переход в секцию текущего состояния. Внутри секции есть конструкция if-else, которая в зависимости от события (пришедшего символа) изменяет текущее состояние:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">size_t</span> length <span style="color: #000080;">=</span> text.<span style="color: #007788;">length</span><span style="color: #008000;">&#40;</span><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;">size_t</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000040;">!</span><span style="color: #000080;">=</span> length<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;">const</span> <span style="color: #0000ff;">char</span> current <span style="color: #000080;">=</span> text<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">switch</span> <span style="color: #008000;">&#40;</span>state<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">case</span> State_Start<span style="color: #008080;">:</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isdigit</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			state <span style="color: #000080;">=</span> State_Number<span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isalpha</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			state <span style="color: #000080;">=</span> State_Word<span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> State_Number<span style="color: #008080;">:</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isspace</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span></pre></td></tr></table></div>

<p>Здесь смотрим на диаграмму – текущее состояние <strong>Number</strong>, событие <strong>Space</strong> (встречен пробельный символ), а значит найдено число:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">			FoundNumber<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> 
			state <span style="color: #000080;">=</span> State_Start<span style="color: #008080;">;</span> 
		<span style="color: #008000;">&#125;</span> 
		<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isdigit</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> 
		<span style="color: #008000;">&#123;</span> 
			state <span style="color: #000080;">=</span> State_Skip<span style="color: #008080;">;</span> 
		<span style="color: #008000;">&#125;</span> 
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> 
	<span style="color: #0000ff;">case</span> State_Word<span style="color: #008080;">:</span> 
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isspace</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> 
		<span style="color: #008000;">&#123;</span> 
			FoundWord<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> 
			state <span style="color: #000080;">=</span> State_Start<span style="color: #008080;">;</span> 
		<span style="color: #008000;">&#125;</span> 
		<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isalpha</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> 
		<span style="color: #008000;">&#123;</span> 
			state <span style="color: #000080;">=</span> State_Skip<span style="color: #008080;">;</span> 
		<span style="color: #008000;">&#125;</span> 
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> 
	<span style="color: #0000ff;">case</span> State_Skip<span style="color: #008080;">:</span> 
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #0000dd;">isspace</span><span style="color: #008000;">&#40;</span>current<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> 
		<span style="color: #008000;">&#123;</span> 
			state <span style="color: #000080;">=</span> State_Start<span style="color: #008080;">;</span> 
		<span style="color: #008000;">&#125;</span> 
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span> 
	<span style="color: #008000;">&#125;</span> 
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p><strong></strong></p>
<p><strong>Итог:</strong></p>
<p>+ Высокая эффективность</p>
<p>+ Простота реализации для простых алгоритмов</p>
<p>&#8212; Тяжело поддерживать</p>
<h2>Интерпретация времени выполнения</h2>
<p>Идея данного подхода проста – надо создать таблицу переходов, заполнить ее, и потом, при наступлении события, найди в таблице следующее состояние и сделать переход:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">enum</span> Events
<span style="color: #008000;">&#123;</span>
	Event_Space,
	Event_Digit,
	Event_Letter,
	Event_Unknown
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> ProcessEvent<span style="color: #008000;">&#40;</span>Events event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
...
&nbsp;
<span style="color: #0000ff;">struct</span> Transition
<span style="color: #008000;">&#123;</span>
	States BaseState_<span style="color: #008080;">;</span>
	Events Event_<span style="color: #008080;">;</span>
	States TargetState_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> AddTransition<span style="color: #008000;">&#40;</span>States fromState, Events event, States toState<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
...
&nbsp;
<span style="color: #0000ff;">typedef</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span>transition<span style="color: #000080;">&gt;</span> TransitionTable<span style="color: #008080;">;</span>
&nbsp;
TransitionTable Transitions_<span style="color: #008080;">;</span>
States CurrentState_<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Заполнение таблицы:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">AddTransition<span style="color: #008000;">&#40;</span>State_Start,	Event_Digit,	State_Number<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
AddTransition<span style="color: #008000;">&#40;</span>State_Start,	Event_Letter,	State_Word<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
AddTransition<span style="color: #008000;">&#40;</span>State_Number,	Event_Space,	State_Start<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
AddTransition<span style="color: #008000;">&#40;</span>State_Number,	Event_Letter,	State_Skip<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
AddTransition<span style="color: #008000;">&#40;</span>State_Number,	Event_Unknown,	State_Skip<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
AddTransition<span style="color: #008000;">&#40;</span>State_Word,	Event_Space,	State_Start<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
AddTransition<span style="color: #008000;">&#40;</span>State_Word,	Event_Digit,	State_Skip<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
AddTransition<span style="color: #008000;">&#40;</span>State_Word,	Event_Unknown,	State_Skip<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
AddTransition<span style="color: #008000;">&#40;</span>State_Skip,	Event_Space,	State_Start<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Получилось довольно наглядно. Платой за наглядность будет более медленная работа автомата, что впрочем, часто не имеет значения.</p>
<p>Чтобы автомат, при наступлении некоторых событий, мог оповестить некоторый код, можно добавить в структуру с информацией о переходе (<strong>Transition</strong>) указатель на функцию (<strong>Action</strong>), которая будет вызываться:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">void</span> <span style="color: #008000;">&#40;</span>DynamicMachine<span style="color: #008080;">::</span><span style="color: #000040;">*</span>Action<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">struct</span> Transition
<span style="color: #008000;">&#123;</span>
	States BaseState_<span style="color: #008080;">;</span>
	Events Event_<span style="color: #008080;">;</span>
	States TargetState_<span style="color: #008080;">;</span>
	Action Action_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
...
&nbsp;
<span style="color: #0000ff;">void</span> AddTransition<span style="color: #008000;">&#40;</span>States fromState, Events event, States toState, Action action<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
...
&nbsp;
<span style="color: #007788;">AddTransition</span><span style="color: #008000;">&#40;</span>State_Number, Event_Space, State_Start, <span style="color: #000040;">&amp;</span>DynamicMachine<span style="color: #008080;">::</span><span style="color: #007788;">FoundNumber</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p><strong></strong></p>
<p><strong>Итог:</strong></p>
<p>+ Гибкость и наглядность</p>
<p>+ Проще поддерживать</p>
<p>&#8212; Меньшая производительность по сравнению с switch-блоками</p>
<h2>Интерпретация времени исполнения. Оптимизация по скорости</h2>
<p>Можно ли объединить наглядность со скоростью? Сделать автомат настолько же эффективным, как автомат на switch-блоках вряд ли удастся, но сократить разрыв можно. Для этого надо из таблицы, построить матрицу, такую, чтобы для получения информации о переходе не выполнять поиск, а сделать выборку по номеру состояния и события:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span> Transition
<span style="color: #008000;">&#123;</span>
	States TargetState_<span style="color: #008080;">;</span>
	Action Action_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">typedef</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span>Transition<span style="color: #000080;">&gt;</span> TransitionByEventsTable<span style="color: #008080;">;</span>
<span style="color: #0000ff;">typedef</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span>TransitionByEventsTable<span style="color: #000080;">&gt;</span> StatesTable<span style="color: #008080;">;</span>
&nbsp;
StatesTable States_<span style="color: #008080;">;</span>
States CurrentState_<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Здесь из вектора <strong>States_</strong> по номеру текущего состояния, можно получить вектор с переходами (<strong>Transition</strong>), где индексом служит номер события. Таким образом поиск состояния для перехода выполняется за время <strong>O(1)</strong>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">const</span> TransitionByEventsTable<span style="color: #000040;">&amp;</span> transitionByEvents <span style="color: #000080;">=</span> States_<span style="color: #008000;">&#91;</span>CurrentState_<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">const</span> Transition<span style="color: #000040;">&amp;</span> transition <span style="color: #000080;">=</span> transitionByEvents<span style="color: #008000;">&#91;</span>event<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Достигается результат, за счет расхода памяти.</p>
<p><strong>Итог:</strong></p>
<p>+ Гибкость, наглядность</p>
<p>+ Эффективен</p>
<p>&#8212; Расход памяти (скорее всего несущественно)</p>
<h2>Boost Statechart</h2>
<p>Мы обсудили несколько способов самостоятельной реализации конечного автомата. Для разнообразия предлагаю рассмотреть библиотеку для построения автоматов из Boost. Данная библиотека очень мощная, предлагаемые возможности позволяют построить очень сложные конечные автоматы. Мы же рассмотрим ее довольно бегло.</p>
<p>Итак, сначала определим события:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">namespace</span> Events
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">struct</span> Digit	<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">event</span><span style="color: #000080;">&lt;</span>Digit<span style="color: #000080;">&gt;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">struct</span> Letter	<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">event</span><span style="color: #000080;">&lt;</span>Letter<span style="color: #000080;">&gt;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">struct</span> Space	<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">event</span><span style="color: #000080;">&lt;</span>Space<span style="color: #000080;">&gt;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">struct</span> Unknown	<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">event</span><span style="color: #000080;">&lt;</span>Unknown<span style="color: #000080;">&gt;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Саму машину (обратите внимание, что второй параметр шаблона – начальное состояние):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">struct</span> Machine	<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">state_machine</span><span style="color: #000080;">&lt;</span>Machine, States<span style="color: #008080;">::</span><span style="color: #007788;">Start</span><span style="color: #000080;">&gt;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И собственно сами состояния. Внутри состояний требуется определить тип описывающий переходы (<strong>reactions</strong>), а если переходов несколько, то перечислить их в списке типов <a href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html">boost::mpl::list</a>. Второй параметр шаблона <strong>simple_state</strong> – тип описывающий машину. Переходы описываются параметрами шаблона transition, парой <strong>Событие &#8212; Следующее состояние</strong>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">namespace</span> States
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">struct</span> Start
		<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">simple_state</span><span style="color: #000080;">&lt;</span>Start, Machine<span style="color: #000080;">&gt;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">mpl</span><span style="color: #008080;">::</span><span style="color: #007788;">list</span>
		<span style="color: #000080;">&lt;</span>
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Digit</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Number</span><span style="color: #000080;">&gt;</span>,
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Letter</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Word</span><span style="color: #000080;">&gt;</span>
		<span style="color: #000080;">&gt;</span>
		reactions<span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">struct</span> Number
		<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">simple_state</span><span style="color: #000080;">&lt;</span>Number, Machine<span style="color: #000080;">&gt;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">mpl</span><span style="color: #008080;">::</span><span style="color: #007788;">list</span>
		<span style="color: #000080;">&lt;</span>
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Space</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Start</span><span style="color: #000080;">&gt;</span>,
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Letter</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Skip</span><span style="color: #000080;">&gt;</span>,
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Unknown</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Skip</span><span style="color: #000080;">&gt;</span>
		<span style="color: #000080;">&gt;</span>
		reactions<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">struct</span> Word
		<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">simple_state</span><span style="color: #000080;">&lt;</span>Word, Machine<span style="color: #000080;">&gt;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">mpl</span><span style="color: #008080;">::</span><span style="color: #007788;">list</span>
		<span style="color: #000080;">&lt;</span>
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Space</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Start</span><span style="color: #000080;">&gt;</span>,
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Digit</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Skip</span><span style="color: #000080;">&gt;</span>,
			boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Unknown</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Skip</span><span style="color: #000080;">&gt;</span>
		<span style="color: #000080;">&gt;</span>
		reactions<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #0000ff;">struct</span> Skip
		<span style="color: #008080;">:</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">simple_state</span><span style="color: #000080;">&lt;</span>Skip, Machine<span style="color: #000080;">&gt;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">statechart</span><span style="color: #008080;">::</span><span style="color: #007788;">transition</span><span style="color: #000080;">&lt;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Space</span>,	States<span style="color: #008080;">::</span><span style="color: #007788;">Start</span><span style="color: #000080;">&gt;</span> reactions<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Машина построена, осталось только инициализировать ее и можно использовать:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Machine machine<span style="color: #008080;">;</span>
machine.<span style="color: #007788;">initiate</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
...
&nbsp;
<span style="color: #007788;">machine</span>.<span style="color: #007788;">process_event</span><span style="color: #008000;">&#40;</span>Events<span style="color: #008080;">::</span><span style="color: #007788;">Space</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p><strong>Итог:</strong></p>
<p>+ Гибкость, расширяемость</p>
<p>&#8212; Эффективность</p>
<h2>Быстродействие</h2>
<p>Я написал тестовую программу для проверки быстродействия построенных автоматов. Через автоматы я прогнал текст размером ~17 Мб. Вот результаты прогона:</p>
<pre>Loading text
Text length: 17605548 bytes
0.19 s

Running BoostMachine
Words: 998002, numbers: 6816
0.73 s

Running DynamicMachine
Words: 998002, numbers: 6816
0.56 s

Running FastDynamicMachine
Words: 998002, numbers: 6816
0.29 s

Running SimpleMachine
Words: 998002, numbers: 6816
0.20 s</pre>
<h2>Что осталось не рассмотренным</h2>
<p>Неохваченными остались еще несколько реализаций конечных автоматов (рекомендую <a href="http://www.rsdn.ru/article/alg/Static_Finite_State_Machine.xml">http://www.rsdn.ru/article/alg/Static_Finite_State_Machine.xml</a> и <a href="http://www.rsdn.ru/article/alg/FiniteStateMachine.xml">http://www.rsdn.ru/article/alg/FiniteStateMachine.xml</a>), генераторы строящие автоматы из описаний, библиотека <a href="http://www.boost.org/doc/libs/release/libs/msm/index.html">Meta State Machine</a> из Boost версии 1.44.0, а также формальные описания конечных автоматов. Со всем перечисленным любопытный читатель может ознакомиться самостоятельно.</p>
<h2>Исходный код автоматов и тестовой программы</h2>
<p><a href="http://www.devexp.ru/wp-content/uploads/2011/02/state_machines.zip">http://www.devexp.ru/wp-content/uploads/2011/02/state_machines.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2011/02/konechnye-avtomaty-v-c/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Использование Cppcheck для статического анализа кода</title>
		<link>http://www.devexp.ru/2011/01/ispolzovanie-cppcheck-dlya-staticheskogo-analiza-koda/</link>
		<comments>http://www.devexp.ru/2011/01/ispolzovanie-cppcheck-dlya-staticheskogo-analiza-koda/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 18:29:11 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Инструменты]]></category>
		<category><![CDATA[Cppcheck]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2011/01/ispolzovanie-cppcheck-dlya-staticheskogo-analiza-koda/</guid>
		<description><![CDATA[Что такое статический анализатор кода? Это программа, которая проверяет исходный код программы и пытается найти в нем ошибки. Иногда это у нее ловко получается. Диагностируются выходы за границы массивов, утечки памяти, использование неинициализированных переменных и прочие неприятные вещи. Часто минутный прогон программы позволяет сэкономить час работы в отладчике в поисках бага. Цена вопроса Есть программы [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Что такое статический анализатор кода? Это программа, которая проверяет исходный код программы и пытается найти в нем ошибки. Иногда это у нее ловко получается. Диагностируются выходы за границы массивов, утечки памяти, использование неинициализированных переменных и прочие неприятные вещи. Часто минутный прогон программы позволяет сэкономить час работы в отладчике в поисках бага.</p>
<h2>Цена вопроса</h2>
<p>Есть программы которые стоят немалых денег (<a href="http://www.coverity.com/html/prevent-for-c-c++.html">Coverity Prevent for C/C++</a>, <a href="http://www.klocwork.com/">Klocwork</a>), а есть абсолютно бесплатные (<a href="http://cppcheck.sourceforge.net/">Cppcheck</a>).</p>
<p>Платные я не тестировал, но судя по <a href="http://easy-coding.blogspot.com/2009/02/blog-post_23.html">статье</a>, Cppcheck им нисколько не уступает. Так на тесте приведенном в указанной статье она находит все ошибки. Вот результат работы:</p>
<pre>Checking check.cpp... 
[check.cpp:11]: (error) Array 'c[10]' index 10 out of bounds 
[check.cpp:5]: (error) Memory leak: __p 
[check.cpp:17]: (error) Memory leak: a 
[check.cpp:14]: (error) Mismatching allocation and deallocation: A::__p 
[check.cpp:8]: (error) Null pointer dereference </pre>
<p>&#160;</p>
<p>Кроме затрат материальных, у инструментов есть определенный уровень вхождения, который некоторых может остановить. Я человек ленивый, поэтому мне особенно приятно, что у данного инструмента этот порог очень низкий.</p>
<p>Есть версия программы с графическим интерфейсом, где единственное усилие которое нужно сделать – выбрать пункт меню <strong>Check-&gt;Files</strong> для проверки одного файла, или <strong>Check-&gt;Directory </strong>для проверки всей директории, после чего просмотреть результаты работы.</p>
<p>Также есть консольная версия, на вход которой также достаточно подать&#160; имена проверяемых файлов.</p>
<h2>Интеграция в систему сборки</h2>
<p>Уже упомянутую консольную версию программы легко добавить в скрипт сборки проекта, чтобы автоматически проводить проверку. При этом Cppcheck может в случае нахождения ошибок вернуть определенный код. Используйте для этого ключ <strong>&#8212;error-exitcode=код_возврата</strong>.</p>
<h2>Вывод</h2>
<p>Cppcheck отличный инструмент, очень простой в использовании, бесплатный и довольно эффективный. Крайне рекомендую к использованию. Есть версии как для Windows, так и для Linux.</p>
<p>Домашняя страница проекта: <a href="http://cppcheck.sourceforge.net/">http://cppcheck.sourceforge.net/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2011/01/ispolzovanie-cppcheck-dlya-staticheskogo-analiza-koda/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Use of undefined type</title>
		<link>http://www.devexp.ru/2010/03/use-of-undefined-type/</link>
		<comments>http://www.devexp.ru/2010/03/use-of-undefined-type/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 18:47:25 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2010/03/use-of-undefined-type/</guid>
		<description><![CDATA[Давайте поговорим о неприятных граблях связанных с удалением неполного типа, что может привести к крайне неприятным последствиям, например милому сердцу Segmentation fault. Связано это с двумя вещами: Полномочиями данными компилятору автоматически генерировать деструктор, если он не определен в классе Возможностью вызвать оператор delete для объекта тип которого в точке удаления еще не известен Рассмотрим простой [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Давайте поговорим о неприятных граблях связанных с удалением неполного типа, что может привести к крайне неприятным последствиям, например милому сердцу <strong>Segmentation fault</strong>. Связано это с двумя вещами:</p>
<ol>
<li>Полномочиями данными компилятору автоматически генерировать деструктор, если он не определен в классе </li>
<li>Возможностью вызвать оператор delete для объекта тип которого в точке удаления еще не известен </li>
</ol>
<p>Рассмотрим простой код и посмотрим, что делает компилятор:</p>
<p><strong>test.h</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef TEST_H</span>
<span style="color: #339900;">#define TEST_H</span>
&nbsp;
<span style="color: #0000ff;">class</span> Test
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Test<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	~Test<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: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif//TEST_H</span></pre></td></tr></table></div>

<p><strong>test.cpp</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;test.h&quot;</span>
&nbsp;
Test<span style="color: #008080;">::</span><span style="color: #007788;">Test</span><span style="color: #008000;">&#40;</span><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: #FF0000;">&quot;Test&quot;</span> <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>
&nbsp;
Test<span style="color: #008080;">::</span>~Test<span style="color: #008000;">&#40;</span><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: #FF0000;">&quot;~Test&quot;</span> <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></pre></td></tr></table></div>

<p><strong>trouble.h</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef TROUBLE_H</span>
<span style="color: #339900;">#define TROUBLE_H</span>
&nbsp;
<span style="color: #339900;">#include &lt;memory&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Test<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Trouble
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Trouble<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	std<span style="color: #008080;">::</span><span style="color: #007788;">auto_ptr</span><span style="color: #000080;">&lt;</span>Test<span style="color: #000080;">&gt;</span> Test_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif//TROUBLE_H</span></pre></td></tr></table></div>

<p><strong>trouble.cpp</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;test.h&quot;</span>
&nbsp;
<span style="color: #339900;">#include &quot;trouble.h&quot;</span>
&nbsp;
Trouble<span style="color: #008080;">::</span><span style="color: #007788;">Trouble</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008080;">:</span> Test_<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">new</span> Test<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: #008000;">&#125;</span></pre></td></tr></table></div>

<p><strong>main.cpp</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;trouble.h&quot;</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;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> 
<span style="color: #008000;">&#123;</span>
	Trouble trouble<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>Итак, имеется два класса: Test и Trouble, причем в целях ускорения компиляции разработчик решил сделать предварительное объявление класса Test в trouble.h, но не написал деструктор для класса Trouble, а значит компилятор заботливо создаст деструктор сам. Когда он это сделает? Вообще компилятор не мечется по коду, а последовательно его анализирует. </p>
<p>Начнет он с функции main в main.cpp, определит, что создается объект trouble типа Trouble из trouble.h, обнаружит конструктор. </p>
<p>Далее он сделает вывод, что по выходу из main объект trouble должен быть удален, попытается найти деструктор, не найдет его и создаст его сам. </p>
<p>Что будет в этом деструкторе? Естественно удаление членов класса, то есть в данном случае std::auto_ptr&lt;Test&gt;, в деструкторе которого будет соответственно вызван оператор delete для указателя на Test. </p>
<p>Внимательно следим за руками! В данном месте компилятор еще ничего не знает о типе Test, поскольку еще не дошел до test.h и поэтому оператор delete будет применен к неполному типу, что вызовет неопределенное поведение. </p>
<p>Откомпилировав приведенный код и выполнив программу вы скорее всего на выводе получите только сообщение из конструктора, деструктор для Test вызван не будет!</p>
<p>Далее подробности и методы борьбы с данным явлением.</p>
<p><span id="more-73"></span></p>
<p>Что делать? Можно сделать неправильный вывод, что предварительное объявление зло и всегда включать все заголовочные файлы в *.h, что приведет к резко возросшему времени компиляции при изменении заголовочных файлов, так как при этом будут перекомпилированы все заголовочные файлы включающие измененный. В больших проектах это может стать настоящей проблемой. Поэтому будем действовать разумно.</p>
<h2>Решение №1</h2>
<p>Всегда объявлять деструктор в *.h и определять его в *.cpp. В этом случае компиляция деструктора произойдет в том месте, где для типа Test есть уже полная информация.</p>
<h2>Решение №2. Boost в помощь</h2>
<p>Хотя некоторые компиляторы предупреждают о проблеме в данной ситуации, но имеет смысл подстраховаться. Не используйте std::auto_ptr! Используйте вместо него boost::scoped_ptr, который заставит вас написать деструктор, выдавая ошибки вроде:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">C:\libs\boost-1.41.0\boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">32</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : error C2027: use of undefined <span style="color: #7a0874; font-weight: bold;">type</span> <span style="color: #ff0000;">'Test'</span>
c:\work\undefined_type\trouble.h<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">9</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : see declaration of <span style="color: #ff0000;">'Test'</span>
C:\libs\boost-1.41.0\boost<span style="color: #000000; font-weight: bold;">/</span>smart_ptr<span style="color: #000000; font-weight: bold;">/</span>scoped_ptr.hpp<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">80</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : see reference to <span style="color: #000000; font-weight: bold;">function</span> template instantiation <span style="color: #ff0000;">'void boost::checked_delete&lt;T&gt;(T *)'</span> being compiled
	with
	<span style="color: #7a0874; font-weight: bold;">&#91;</span>
		<span style="color: #007800;">T</span>=Test
	<span style="color: #7a0874; font-weight: bold;">&#93;</span>
C:\libs\boost-1.41.0\boost<span style="color: #000000; font-weight: bold;">/</span>smart_ptr<span style="color: #000000; font-weight: bold;">/</span>scoped_ptr.hpp<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">76</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000; font-weight: bold;">while</span> compiling class template member <span style="color: #000000; font-weight: bold;">function</span> <span style="color: #ff0000;">'boost::scoped_ptr&lt;T&gt;::~scoped_ptr(void)'</span>
	with
	<span style="color: #7a0874; font-weight: bold;">&#91;</span>
		<span style="color: #007800;">T</span>=Test	
	<span style="color: #7a0874; font-weight: bold;">&#93;</span>
c:\work\undefined_type\trouble.h<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">18</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : see reference to class template instantiation <span style="color: #ff0000;">'boost::scoped_ptr&lt;T&gt;'</span> being compiled
	with
	<span style="color: #7a0874; font-weight: bold;">&#91;</span>
		<span style="color: #007800;">T</span>=Test
	<span style="color: #7a0874; font-weight: bold;">&#93;</span>
C:\libs\boost-1.41.0\boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">32</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> : error C2118: negative subscript</pre></td></tr></table></div>

<p>Или:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp: In <span style="color: #000000; font-weight: bold;">function</span> ‘void boost::checked_delete<span style="color: #7a0874; font-weight: bold;">&#40;</span>T<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>with T = Test<span style="color: #7a0874; font-weight: bold;">&#93;</span>’:
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>smart_ptr<span style="color: #000000; font-weight: bold;">/</span>scoped_ptr.hpp:<span style="color: #000000;">80</span>: instantiated from ‘boost::scoped_ptr<span style="color: #000000; font-weight: bold;">&lt;</span>T<span style="color: #000000; font-weight: bold;">&gt;</span>::~scoped_ptr<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>with T = Test<span style="color: #7a0874; font-weight: bold;">&#93;</span>’
<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>tma<span style="color: #000000; font-weight: bold;">/</span>Documents<span style="color: #000000; font-weight: bold;">/</span>undefined_type<span style="color: #000000; font-weight: bold;">/</span>trouble.h:<span style="color: #000000;">15</span>: instantiated from here
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp:<span style="color: #000000;">32</span>: error: invalid application of ‘sizeof’ to incomplete <span style="color: #7a0874; font-weight: bold;">type</span> ‘Test’ 
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp:<span style="color: #000000;">32</span>: error: creating array with negative <span style="color: #c20cb9; font-weight: bold;">size</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>‘-0x000000001’<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp:<span style="color: #000000;">33</span>: error: invalid application of ‘sizeof’ to incomplete <span style="color: #7a0874; font-weight: bold;">type</span> ‘Test’ 
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>include<span style="color: #000000; font-weight: bold;">/</span>boost<span style="color: #000000; font-weight: bold;">/</span>checked_delete.hpp:<span style="color: #000000;">33</span>: error: creating array with negative <span style="color: #c20cb9; font-weight: bold;">size</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>‘-0x000000001’<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></td></tr></table></div>

<p>Причина ошибки – проверка осуществляемая scoped_ptr перед вызовом delete для объекта. Суть проверки в попытке создания массива:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> <span style="color: #0000ff;">char</span> type_must_be_complete<span style="color: #008000;">&#91;</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>T<span style="color: #008000;">&#41;</span><span style="color: #008080;">?</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">:</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span> <span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #008000;">&#41;</span> <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>type_must_be_complete<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>В случае неполного типа будет предпринята попытка создания массива длиной –1, что приведет к ошибке компиляции.</p>
<p>Если по каким либо причинам использовать boost::scoped_ptr нельзя, используйте boost::shared_ptr. Он не использует проверки, но из-за особенностей его устройства удаление объекта происходит в месте, где уже есть полная информация о его типе.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2010/03/use-of-undefined-type/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>О копировании объектов в C++</title>
		<link>http://www.devexp.ru/2010/03/o-kopirovanii-obektov-v-c/</link>
		<comments>http://www.devexp.ru/2010/03/o-kopirovanii-obektov-v-c/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 21:18:36 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2010/03/o-kopirovanii-obektov-v-c/</guid>
		<description><![CDATA[Я регулярно сталкиваюсь с ошибками связанными с невнимательностью или незнанием механизма копирования объектов в C++. Поэтому первое правило: Не копируйте! Задайте себе вопрос, действительно ли класс должен поддерживать копирование? Скорее всего это не нужно как по соображениям эффективности (передавать объект по ссылке или указателю менее накладно, чем создавать его копию при передаче по значению), так [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Я регулярно сталкиваюсь с ошибками связанными с невнимательностью или незнанием механизма копирования объектов в C++. Поэтому первое правило:</p>
<h2>Не копируйте!</h2>
<p>Задайте себе вопрос, действительно ли класс должен поддерживать копирование? Скорее всего это не нужно как по соображениям эффективности (передавать объект по ссылке или указателю менее накладно, чем создавать его копию при передаче по значению), так и просто исходя из здравого смысла – зачем две копии объекта, представляющего к примеру базу данных с пользователями или порт? Поэтому сделайте класс некопируемым. Для этого надо перенести объявления копирующего конструктора и оператора присваивания в защищенную секцию (определять их необязательно):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Port
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Port<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">virtual</span> ~Port<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	Port<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Port<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	Port<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Port<span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>В этом случае при попытке скопировать объект возникнет ошибка компиляции из-за недоступности либо конструктора копирования, либо оператора присваивания.</p>
<p>Но чтобы каждый раз не писать данный код и дать людям ясно понять чего вы хотите, унаследуйте класс от boost::noncopyable:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/noncopyable.hpp&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Port
	<span style="color: #008080;">:</span> <span style="color: #0000ff;">private</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">noncopyable</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Port<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">virtual</span> ~Port<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: #008080;">;</span></pre></td></tr></table></div>

<p>На этом можно остановиться, но если же вы решили, что класс должен поддерживать копирование, то читайте дальше.</p>
<p><span id="more-72"></span></p>
<h2>Функции создаваемые компилятором</h2>
<p>Компилятор будет стараться вам помочь и если вы не написали конструктор по умолчанию, деструктор, оператор присваивания или копирующий конструктор, создаст их сам. Причем созданы они будут только если они действительно требуются. Рассмотрим простой класс:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Message
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">unsigned</span> Id_<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> Text_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>При его создании компилятор автоматически создаст конструктор по умолчанию в котором будет вызван конструктор по умолчанию для каждого из членов, но только если член не является встроенным типом (int, double и т.д.) и деструктор:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Message<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008080;">:</span> Text_<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>При копировании:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Message m1<span style="color: #008080;">;</span>
Message m2<span style="color: #008080;">;</span>
m1 <span style="color: #000080;">=</span> m2<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Будет автоматически сгенерирован оператор присваивания, который вызовет оператор присваивания для каждого члена:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Message<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Message<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Id_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Id_</span><span style="color: #008080;">;</span>
	Text_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Text_</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Здесь я хочу обратить внимание на то, что оператор присваивания возвращает ссылку на *this. Это нужно для того, чтобы запись вида</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">m1 <span style="color: #000080;">=</span> m2 <span style="color: #000080;">=</span> m3<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>была законна. Это общепринятое поведение, поэтому если будете писать свой оператор присваивания, постарайтесь придерживаться общепринятой формы.</p>
<p>Копирующий конструктор будет создан если вы напишете:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Message m1<span style="color: #008080;">;</span>
Message m2<span style="color: #008000;">&#40;</span>m1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И как и ожидается, он проинициализирует каждый член конструируемого объекта значением из другого объекта:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Message<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Message<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
	<span style="color: #008080;">:</span> Id_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Id_</span><span style="color: #008000;">&#41;</span>
	, Text_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Text_</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Конструктор, копирующий конструктор и оператор присваивания не будет создан автоматически, если класс содержит константный член или член являющийся ссылкой.</p>
<p>Теперь следующее правило:</p>
<h2>Дайте компилятору помочь вам</h2>
<p>Не мешайте компилятору написать за вас оператор присваивания и копирующий конструктор – в отличии от нас он не забудет скопировать каждый из членов. Особенно часто программисты забывают при добавлении нового члена в класс обновить также и данные методы. Компилятор обиженный отказом от предложенной помощи не скажет вам, что класс копируется не полностью!</p>
<h2>Копируйте полностью</h2>
<p>Но иногда помощь компилятора бывает неуместна. Например необходимо чтобы каждый объект содержал уникальный идентификатор. В таком случае оператор присваивания и копирующий конструктор придется написать самостоятельно:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Message
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Message<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Id_<span style="color: #008000;">&#40;</span>GetId<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: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">virtual</span> ~Message<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	Message<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Message<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Id_<span style="color: #008000;">&#40;</span>GetId<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		, Text_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Text_</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	Message<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Message<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Id_ <span style="color: #000080;">=</span> GetId<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		Text_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Text_</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">unsigned</span> Id_<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> Text_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Здесь присутствует одна проблема, о которой поговорим позже, а пока все выглядит неплохо. Но давайте создадим класс на основе Message:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> DataMessage
	<span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Message
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	DataMessage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Data_<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	~DataMessage<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	DataMessage<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> DataMessage<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Data_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Data_</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	DataMessage<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> DataMessage<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Data_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Data_</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	CompressedData Data_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Все отлично, но есть проблема – члены Message больше не копируются, так как новые копирующий конструктор и оператор присваивания скрыли те же методы родительского класса, а значит придется их вызвать явно:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">DataMessage<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> DataMessage<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
	<span style="color: #008080;">:</span> Message<span style="color: #008000;">&#40;</span>from<span style="color: #008000;">&#41;</span>
	, Data_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Data_</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
DataMessage<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> DataMessage<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Message<span style="color: #008080;">::</span><span style="color: #007788;">operator</span><span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span>from<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	Data_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Data_</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<blockquote>
<p>Кстати напомню, что инициализация членов происходит в порядке их объявления в классе, а не в порядке следования в секции инициализации конструктора. Опасайтесь багов такого рода:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Customer
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Customer<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> firstName, <span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> secondName<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	HashType Hash_<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> FirstName_<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #007788;">string</span> SecondName_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
Customer<span style="color: #008080;">::</span><span style="color: #007788;">Customer</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> firstName, <span style="color: #0000ff;">const</span> std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000040;">&amp;</span> secondName<span style="color: #008000;">&#41;</span>
	<span style="color: #008080;">:</span> FirstName_<span style="color: #008000;">&#40;</span>firstName<span style="color: #008000;">&#41;</span>
	, SecondName_<span style="color: #008000;">&#40;</span>secondName<span style="color: #008000;">&#41;</span>
	, Hash_<span style="color: #008000;">&#40;</span>GetHash<span style="color: #008000;">&#40;</span>FirstName_ <span style="color: #000040;">+</span> SecondName_<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Ой! Мы хотим получить хэш от еще не инициализированных строк!</p>
</blockquote>
<p>Теперь о проблеме которая осталась – мы не проверяем присваивание самому себе. Следующее правило:</p>
<h2>Проверяйте на присваивание самому себе</h2>
<p>Конечно вы никогда не напишите</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">message <span style="color: #000080;">=</span> message<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>А как насчет этого:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">Messages<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> Messages<span style="color: #008000;">&#91;</span>j<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>В любом случае, по закону Мерфи, если уж что-то можно сделать неправильно, то это будет сделано. Просто защитите себя от этого:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">DataMessage<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> DataMessage<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span> <span style="color: #000080;">==</span> <span style="color: #000040;">&amp;</span>from<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	Message<span style="color: #008080;">::</span><span style="color: #007788;">operator</span><span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span>from<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	Data_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Data_</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Также можно например писать о некорректном присваивании в лог ошибок.</p>
<p>Теперь можно поговорить о устранении дублирования кода в операторе присваивания и копирующем конструкторе. Буду краток:</p>
<h2>Не пытайтесь реализовать оператор присваивания через копирующий конструктор или наоборот</h2>
<p>У вас ничего не выйдет. И хотя делают они очень много похожего, но по своей сути они слишком разные чтобы их удалось скрестить. В первом случае вы будете создавать объект который уже существует, во втором присваивать что-то еще не созданному объекту. Единственное, что можно сделать – это выделить общий код в отдельную функцию вызываемую обоими методами:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> Sensor
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	Sensor<span style="color: #008000;">&#40;</span>Controller<span style="color: #000040;">*</span> controller<span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Controller_<span style="color: #008000;">&#40;</span>controller<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	~Sensor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Shutdown<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	Sensor<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Sensor<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
		<span style="color: #008080;">:</span> Controller_<span style="color: #008000;">&#40;</span>from.<span style="color: #007788;">Controller_</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	Sensor<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> Sensor<span style="color: #000040;">&amp;</span> from<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span> <span style="color: #000080;">==</span> <span style="color: #000040;">&amp;</span>from<span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">return</span> <span style="color: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		Shutdown<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		Controller_ <span style="color: #000080;">=</span> from.<span style="color: #007788;">Controller_</span><span style="color: #008080;">;</span>
		Init<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: #000040;">*</span><span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">void</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">// Тут может быть что угодно</span>
		Controller_<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Register<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">void</span> Shutdown<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #666666;">// Тут может быть что угодно</span>
		Controller_<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Unregister<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">this</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	Controller<span style="color: #000040;">*</span> Controller_<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Но и здесь зоркий глаз может обнаружить проблему. Последнее правило:</p>
<h2>Напишите безопасный в смысле исключений оператор присваивания</h2>
<p>Дело в том, что в предыдущем примере, если из Init в операторе присваивания вылетит исключение, объект останется в несогласованном состоянии, так как был вызван метод Shutdown, но повторная инициализация проведена не была. Рассмотрение данного вопроса выходит за рамки заметки, поэтому посоветую обратиться к <strong>Правилу 29: Стремитесь, чтобы программа была безопасна относительно исключений</strong> из книги <strong>Эффективное использование C++ 55 верных советов улучшить структуру и код ваших программ</strong> Скотта Мэйерса.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2010/03/o-kopirovanii-obektov-v-c/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Архивирование с библиотеками zlib и bzip2/libbzip2 используя Boost Iostreams</title>
		<link>http://www.devexp.ru/2010/03/arxivirovanie-s-bibliotekami-zlib-i-bzip2libbzip2-ispolzuya-boost-iostreams/</link>
		<comments>http://www.devexp.ru/2010/03/arxivirovanie-s-bibliotekami-zlib-i-bzip2libbzip2-ispolzuya-boost-iostreams/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 19:59:18 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[Boost]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2010/03/arxivirovanie-s-bibliotekami-zlib-i-bzip2libbzip2-ispolzuya-boost-iostreams/</guid>
		<description><![CDATA[Недавно у меня возникла задача добавить сжатие данных в программу. Сразу нашлось две свободных библиотеки – zlib и libbzip2 написанные на C. Изучив вопрос глубже, оказалось что писать удобные обертки над функциями на C не нужно, так как в Boost IOStreams все уже написано. О том как добавить данный функционал и правильно собрать проект я [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Недавно у меня возникла задача добавить сжатие данных в программу. Сразу нашлось две свободных библиотеки – <a href="http://zlib.net/" target="_blank">zlib</a> и <a href="http://www.bzip.org/" target="_blank">libbzip2</a> написанные на C. Изучив вопрос глубже, оказалось что писать удобные обертки над функциями на C не нужно, так как в <a href="http://www.boost.org/doc/libs/1_42_0/libs/iostreams/doc/index.html" target="_blank">Boost IOStreams</a> все уже написано.</p>
<p>О том как добавить данный функционал и правильно собрать проект я расскажу в данной заметке. Также будет приведен пример кода для сжатия и распаковки файлов и сравнение zlib (алгоритм <strong>DEFLATE</strong>, методы <strong>gzip</strong> и <strong>zlib</strong>) и libbzip2 (алгоритм <strong>bzip2</strong>) по скорости работы и уровню сжатия тестовых, бинарных и исполняемых файлов.</p>
<p> <span id="more-71"></span>
<p>Я не буду рассматривать интерфейсы данных библиотек, так как Boost предоставляет довольно удобную абстракцию. Суть абстракции в следующем – имеются устройства представляющие собой например файл отрытый для записи, фильтры, например архивирующий и есть возможность создать фильтрующий поток, содержащий устройство и цепочку из произвольных фильтров. Таким образом создав фильтр сжимающий переданные в него данные и соединив его с устройством пишущим в файл мы получим готовое решение для сжатия и записи данных. Соответственно чтобы распаковать сжатый файл, нам нужно создать устройство представляющее открытый для чтения файл, фильтр который будет распаковывать поступающие в него данные и соединить их.</p>
<p>Сразу приведу код, который рассмотрю ниже:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">filtering_ostreambuf</span> out<span style="color: #008080;">;</span>
out.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">bzip2_compressor</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
out.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">file_sink</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;data.bin&quot;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">ios</span><span style="color: #008080;">::</span><span style="color: #007788;">binary</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">copy</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">file_source</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;data.bz2&quot;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">ios</span><span style="color: #008080;">::</span><span style="color: #007788;">binary</span><span style="color: #008000;">&#41;</span>, out<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
...
<span style="color: #007788;">boost</span><span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">filtering_istreambuf</span> in<span style="color: #008080;">;</span>
in.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">bzip2_decompressor</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
in.<span style="color: #007788;">push</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">file_source</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;data.bz2&quot;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">ios</span><span style="color: #008080;">::</span><span style="color: #007788;">binary</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">copy</span><span style="color: #008000;">&#40;</span>in, boost<span style="color: #008080;">::</span><span style="color: #007788;">iostreams</span><span style="color: #008080;">::</span><span style="color: #007788;">file_sink</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;data.bin&quot;</span>, std<span style="color: #008080;">::</span><span style="color: #007788;">ios</span><span style="color: #008080;">::</span><span style="color: #007788;">binary</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>По сути в этих восьми строках содержится все необходимое для сжатия и распаковки файла. В обоих случаях мы создаем однонаправленный (только на чтение или только на запись) фильтрующий буфер потока. Создаем фильтр осуществляющий сжатие или распаковку, устройство представляющее файл, и соединяем их в буфере. После этого можно используя утилиту copy из Boost Iostreams копировать содержимое другого потока в буфер или наоборот.</p>
<p>Если вместо буфера (filtering_streambuf) использовать поток (filtering_stream), то писать или читать из него можно используя интерфейс потоков C++.</p>
<blockquote>
<p>Устройства в Boost Iostream могут быть источниками (<strong>Source</strong>) или приемниками (<strong>Sink</strong>). Соответственно одни могут поставлять данные по требованию откуда либо, например из файла, а другие наоборот данные только куда то отправляют. Причем вы можете написать свой приемник или источник (это несложно) и создать свое устройство реализующее необходимую абстракцию. Например socket_source и socket_sink позволяющие работать с сокетами, pipe_source и pipe_sink тоже самое для именованных каналов или вообще null_sink (который кстати в Boost уже есть), которое просто получив данные тут же о них забывает. Причем соединив, скажем socket_source с фильтром boost::iostreams::bzip2_compressor вы получите передачу через сокеты сжатых данных, а дописав еще шифрующий фильтр можно получить передачу зашифрованных сжатых данных.</p>
</blockquote>
<h2>Сборка</h2>
<p>Чтобы собрать ваш проект с Boost и одной из библиотек сжатия нужно сделать три вещи:</p>
<ol>
<li>Собрать библиотеку zlib или bzip2/libzip2 и убедиться, что ваша система сборки увидит путь к заголовочным файлам и собранным библиотекам. Кстати на большинстве Unix систем об этом можно не задумываться, так как скорее всего библиотека уже установлена. </li>
<li>Установить при сборке проекта переменную компиляции <strong>BOOST_IOSTREAMS_NO_LIB</strong> </li>
<li>Включить в сборку один из файлов из Boost (в версии 1.41.0 они находятся в <strong>libs/iostreams/src</strong>) в зависимости от используемого метода:
<ul>
<li>zlib – zlib.cpp </li>
<li>gzip – gzip.cpp </li>
<li>bzip2 – bzip2.cpp </li>
</ul>
</li>
</ol>
<h2>Сравнение методов сжатия zlib/gzip/bzip2</h2>
<p>Увлекшись я написал небольшой тест для сравнения описываемых методов. Вот результаты запуска программы:</p>
<h3>Бинарный файл со случайными числами</h3>
<p>Размер: 5 242 880 байт</p>
<table border="0" cellspacing="0" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="15%"><strong>Метод</strong></td>
<td valign="top" width="25%"><strong>Время сжатия, секунд</strong></td>
<td valign="top" width="30%"><strong>Время распаковки, секунд</strong></td>
<td valign="top" width="30%"><strong>Размер сжатого файла, байт</strong></td>
</tr>
<tr>
<td valign="top" width="15%">zlib</td>
<td valign="top" width="25%">0.20</td>
<td valign="top" width="30%">0.15</td>
<td valign="top" width="30%">5 053 306</td>
</tr>
<tr>
<td valign="top" width="15%">gzip</td>
<td valign="top" width="25%">0.18</td>
<td valign="top" width="30%">0.15</td>
<td valign="top" width="30%">5 053 318</td>
</tr>
<tr>
<td valign="top" width="15%">bzip2</td>
<td valign="top" width="25%">0.59</td>
<td valign="top" width="30%">0.77</td>
<td valign="top" width="30%">5 049 795</td>
</tr>
</tbody>
</table>
<h3>&#160;</h3>
<h3>Текстовой файл (несколько мануалов Linux слитые в один файл)</h3>
<p>Размер: 3 534 333 байт</p>
<table border="0" cellspacing="0" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="15%"><strong>Метод</strong></td>
<td valign="top" width="25%"><strong>Время сжатия, секунд</strong></td>
<td valign="top" width="30%"><strong>Время распаковки, секунд</strong></td>
<td valign="top" width="30%"><strong>Размер сжатого файла, байт</strong></td>
</tr>
<tr>
<td valign="top" width="15%">zlib</td>
<td valign="top" width="25%">0.28</td>
<td valign="top" width="30%">0.07</td>
<td valign="top" width="30%">1 050 711</td>
</tr>
<tr>
<td valign="top" width="15%">gzip</td>
<td valign="top" width="25%">0.36</td>
<td valign="top" width="30%">0.08</td>
<td valign="top" width="30%">1 050 723</td>
</tr>
<tr>
<td valign="top" width="15%">bzip2</td>
<td valign="top" width="25%">0.43</td>
<td valign="top" width="30%">0.24</td>
<td valign="top" width="30%">856 572</td>
</tr>
</tbody>
</table>
<h3>&#160;</h3>
<h3>Исполняемый файл</h3>
<p>Размер: 4 568 332 байт</p>
<table border="0" cellspacing="0" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="15%"><strong>Метод</strong></td>
<td valign="top" width="25%"><strong>Время сжатия, секунд</strong></td>
<td valign="top" width="30%"><strong>Время распаковки, секунд</strong></td>
<td valign="top" width="30%"><strong>Размер сжатого файла, байт</strong></td>
</tr>
<tr>
<td valign="top" width="15%">zlib</td>
<td valign="top" width="25%">1.51</td>
<td valign="top" width="30%">0.10</td>
<td valign="top" width="30%">1 636 939</td>
</tr>
<tr>
<td valign="top" width="15%">gzip</td>
<td valign="top" width="25%">1.61</td>
<td valign="top" width="30%">0.10</td>
<td valign="top" width="30%">1 636 951</td>
</tr>
<tr>
<td valign="top" width="15%">bzip2</td>
<td valign="top" width="25%">0.87</td>
<td valign="top" width="30%">0.36</td>
<td valign="top" width="30%">1 439 625</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p>Тест конечно не претендует на серьезное исследование, но определенные выводы сделать позволяет:</p>
<ul>
<li>bzip2 сжимает лучше, но при этом значительно медленнее. </li>
<li>zlib и gzip практически одинаковы. Это правда так, так как они используют один алгоритм, единственное отличие в том, что zlib оптимизирован для сжатия потоковых данных, например из-за этой особенности он используется в протоколе HTTP/1.1, в то время как gz применяется для сжатия файлов. </li>
</ul>
<h2>Файлы к заметке</h2>
<p>По традиции вы можете <a href="http://www.devexp.ru/wp-content/uploads/2010/03/archive.zip" target="_blank">скачать исходный код</a> тестового проекта. Архив содержит код библиотек и файлы для сборки с CMake, таким образом вам нужно только иметь установленный Boost, Cmake и положить в директорию data проекта свои тестовые данные.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2010/03/arxivirovanie-s-bibliotekami-zlib-i-bzip2libbzip2-ispolzuya-boost-iostreams/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Полезные переменные CMake</title>
		<link>http://www.devexp.ru/2010/03/poleznye-peremennye-cmake/</link>
		<comments>http://www.devexp.ru/2010/03/poleznye-peremennye-cmake/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 20:14:35 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[Разработка]]></category>
		<category><![CDATA[Сборка]]></category>
		<category><![CDATA[CMake]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2010/03/poleznye-peremennye-cmake/</guid>
		<description><![CDATA[Крайне полезная информация по переменным CMake находится по адресу http://www.cmake.org/Wiki/CMake_Useful_Variables. После прочтения сами собой отпадают многие вопросы. Ну и напомню, что содержимое переменной XXX можно посмотреть: message (${XXX}) И изменить: set (XXX ${XXX} значение) А также проверить присутствует ли в переменной определенная подстрока: if (XXX MATCHES &#34;подстрока&#34;) ... endif () Если нужно изменить часть содержимого [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Крайне полезная информация по переменным CMake находится по адресу <a href="http://www.cmake.org/Wiki/CMake_Useful_Variables" target="_blank">http://www.cmake.org/Wiki/CMake_Useful_Variables</a>. После прочтения сами собой отпадают многие вопросы.</p>
<p>Ну и напомню, что содержимое переменной XXX можно посмотреть:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cmake" style="font-family:monospace;"><span style="color: #1f3f81; font-style: bold;">message</span> <span style="color: #197d8b;">(</span><span style="color: #b08000;">${XXX}</span><span style="color: #197d8b;">)</span></pre></td></tr></table></div>

<p>И изменить:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cmake" style="font-family:monospace;"><span style="color: #1f3f81; font-style: bold;">set</span> <span style="color: #197d8b;">(</span>XXX <span style="color: #b08000;">${XXX}</span> значение<span style="color: #197d8b;">)</span></pre></td></tr></table></div>

<p>А также проверить присутствует ли в переменной определенная подстрока:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cmake" style="font-family:monospace;"><span style="color: #1f3f81; font-style: bold;">if</span> <span style="color: #197d8b;">(</span>XXX <span style="color: #077807; font-sytle: italic;">MATCHES</span> <span style="color: #912f11;">&quot;подстрока&quot;</span><span style="color: #197d8b;">)</span>
	...
<span style="color: #1f3f81; font-style: bold;">endif</span> <span style="color: #197d8b;">()</span></pre></td></tr></table></div>

<p>Если нужно изменить часть содержимого переменной (например флаг компилятора), то на помощь придут регулярные выражения:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cmake" style="font-family:monospace;"><span style="color: #1f3f81; font-style: bold;">string</span> <span style="color: #197d8b;">(</span><span style="color: #077807; font-sytle: italic;">REGEX</span> <span style="color: #077807; font-sytle: italic;">REPLACE</span> /W[0-4] /W4 CMAKE_CXX_FLAGS <span style="color: #b08000;">${CMAKE_CXX_FLAGS}</span><span style="color: #197d8b;">)</span></pre></td></tr></table></div>

<p>В данном случае будет установлен максимальный уровень предупреждений <strong>/W4</strong> для компилятора от Microsoft.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2010/03/poleznye-peremennye-cmake/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Чтение настроек приложения</title>
		<link>http://www.devexp.ru/2010/02/chtenie-nastroek-prilozheniya/</link>
		<comments>http://www.devexp.ru/2010/02/chtenie-nastroek-prilozheniya/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 14:23:07 +0000</pubDate>
		<dc:creator><![CDATA[Максим Тремпольцев]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Конфигурирование]]></category>
		<category><![CDATA[Разработка]]></category>
		<category><![CDATA[Boost]]></category>

		<guid isPermaLink="false">http://www.devexp.ru/2010/02/chtenie-nastroek-prilozheniya/</guid>
		<description><![CDATA[Мне часто приходится писать гибко конфигурируемые программы. Конфигурационные файлы часто получаются довольно сложными, с развитой иерархией. Для хранения настроек я использовал XML файлы, а разбор конфигурации делал вручную. Недавно (с версии 1.41.0) в Boost появилась библиотека Property Tree, предназначенная для решения данной задачи. Помимо поддержки XML, также поддерживаются форматы INI, JSON и свой формат INFO. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Мне часто приходится писать гибко конфигурируемые программы. Конфигурационные файлы часто получаются довольно сложными, с развитой иерархией. Для хранения настроек я использовал <strong>XML</strong> файлы, а разбор конфигурации делал вручную.</p>
<p>Недавно (с версии 1.41.0) в <strong>Boost</strong> появилась библиотека <a href="http://www.boost.org/doc/libs/1_42_0/libs/property_tree/index.html" target="_blank">Property Tree</a>, предназначенная для решения данной задачи. Помимо поддержки <strong>XML</strong>, также поддерживаются форматы <strong>INI</strong>, <strong>JSON</strong> и свой формат <strong>INFO</strong>. </p>
<p>В данной заметке я рассмотрю указанные форматы и приведу код для разбора файла.</p>
<p> <span id="more-68"></span><br />
<h2>Форматы файлов</h2>
<p>Обойду стороной вопрос об удобстве синтаксиса, так как вопрос этот достаточно субъективный, просто приведу примеры файлов описывающих одну и ту же конфигурацию:</p>
<h3>INI</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">; Комментарий</span>
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>server<span style="">&#93;</span></span>
<span style="color: #000099;">name</span>	<span style="color: #000066; font-weight:bold;">=</span>	<span style="color: #933;">&quot;alpha server&quot;</span>
<span style="color: #000099;">port</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	9010</span>
&nbsp;
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>channels<span style="">&#93;</span></span>
<span style="color: #666666; font-style: italic;">; Иерархии в INI-файлах не поддерживаются</span>
&nbsp;
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>channel<span style="">&#93;</span></span>
<span style="color: #666666; font-style: italic;">; Не работает</span>
<span style="color: #000099;">name</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	first</span>
<span style="color: #000099;">id</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	1</span>
<span style="color: #000099;">comment</span>	<span style="color: #000066; font-weight:bold;">=</span>	<span style="color: #933;">&quot;Необязательный комментарий&quot;</span>
<span style="color: #000099;">enabled</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	true</span>
&nbsp;
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>channel<span style="">&#93;</span></span>
<span style="color: #666666; font-style: italic;">; Не работает</span>
<span style="color: #000099;">name</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	second</span>
<span style="color: #000099;">id</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	2</span>
<span style="color: #000099;">enabled</span>	<span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">	false</span></pre></td></tr></table></div>

<h3>XML</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #808080; font-style: italic;">&lt;!-- Комментарий --&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>alpha server<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;port<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>9010<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/port<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>first<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;comment<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Необязательный комментарий<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/comment<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>second<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/enabled<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channel<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/channels<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>JSON</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">{
	/* Комментарий */
	&quot;server&quot;:
	{
		&quot;name&quot;:	&quot;alpha server&quot;,
		&quot;port&quot;:	9010,
		&quot;channels&quot;:
		[
			{
				&quot;name&quot;:		&quot;first&quot;,
				&quot;id&quot;:		1,
				&quot;comment&quot;:	&quot;Необязательный комментарий&quot;,
				&quot;enabled&quot;:	true
			},
			{
				&quot;name&quot;:		&quot;second&quot;,
				&quot;id&quot;:		2,
				&quot;enabled&quot;:	false
			}
		]
	}
}</pre></td></tr></table></div>

<h3>INFO</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="xml" style="font-family:monospace;">; Комментарий
server
{
	name	&quot;alpha server&quot;
	port	9010
	channels
	{
		channel
		{
			name	&quot;first&quot;
			id	1
			comment	&quot;Необязательный комментарий&quot;
			enabled	true
		}
		channel
		{
			name	&quot;second&quot;
			id	2
			enabled	false
		}
	}
}</pre></td></tr></table></div>

<p>Теперь по существу:</p>
<ol>
<li>Формат INI не поддерживает иерархическое представление данных </li>
<li>C документами сохраненными в UTF-8, проблем при чтении у Boost Property Tree не обнаружено </li>
<li>JSON очень строго регламентирует синтаксис и структуру файла, поэтому при ошибках в файле, например из-за пропущенной запятой, файл разобран не будет </li>
<li>JSON проверяет правильность написания булевых значений – написав &quot;fals&quot; вместо &quot;false&quot;, вы получите ошибку на этапе разбора файла. Внимание, в случае XML и INFO ошибки на будет, а код get&lt;bool&gt;(&quot;&#8230;&quot;) вернет true (как и ожидается, если &quot;false&quot; написан верно, возвращаемое значение будет false). </li>
<li>Во всех форматах корректно идет работа как с целыми числами, так и с числами с плавающей точкой. Возможна запись в виде: 1560, 1560.5, 1.5605e3 </li>
</ol>
<h2>Разбор файла</h2>
<p>Первым делом необходимо подключить один из указанных заголовочных файлов, в зависимости от того, с файлами какого формата вы будете работать:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/property_tree/ini_parser.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/property_tree/xml_parser.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/property_tree/json_parser.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/property_tree/info_parser.hpp&gt;</span></pre></td></tr></table></div>

<p>После этого создается объект типа boost::property_tree::ptree, в котором при удачном разборе файла будет сохранена структура файла со значениями. Далее собственно вызывается функция для разбора файла. Об ошибке во время разбора файла можно вывести подробное сообщение:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree</span> config<span style="color: #008080;">;</span>
<span style="color: #0000ff;">try</span>
<span style="color: #008000;">&#123;</span>
	Parser<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;fileName&quot;</span>, config<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>Exception<span style="color: #000040;">&amp;</span> error<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> error.<span style="color: #007788;">message</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;: &quot;</span> 
		<span style="color: #000080;">&lt;&lt;</span> error.<span style="color: #007788;">filename</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;, line &quot;</span> 
		<span style="color: #000080;">&lt;&lt;</span> error.<span style="color: #007788;">line</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <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></pre></td></tr></table></div>

<p>Parser в четвертой строке и Exception в шестой в зависимости от типа файла принимают следующие значения:</p>
<table border="0" cellspacing="0" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="20%"><strong>Тип файла</strong></td>
<td valign="top"><strong>Parser</strong></td>
<td valign="top"><strong>Exception</strong></td>
</tr>
<tr>
<td valign="top" width="20%">INI</td>
<td valign="top">boost::property_tree::read_ini</td>
<td valign="top">boost::property_tree::ini_parser_error</td>
</tr>
<tr>
<td valign="top" width="20%">XML</td>
<td valign="top">boost::property_tree::read_xml</td>
<td valign="top">boost::property_tree::xml_parser_error</td>
</tr>
<tr>
<td valign="top" width="20%">JSON</td>
<td valign="top">boost::property_tree::read_json</td>
<td valign="top">boost::property_tree::json_parser_error</td>
</tr>
<tr>
<td valign="top" width="20%">INFO</td>
<td valign="top">boost::property_tree::read_info</td>
<td valign="top">boost::property_tree::info_parser_error</td>
</tr>
</tbody>
</table>
<h2>Разбор конфигурации</h2>
<p>После успешно выполненного разбора документ будет представлен узлами содержащими элементы (узел из одного значения) или другие узлы.</p>
<p>Доступ к нужному узлу осуществляется методом:</p>
<table border="0" cellspacing="12" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="30%"><strong>get_child(&quot;имя_узла&quot;)</strong></td>
<td valign="top">Обращение к подузлам возможно с использованием разделителя .</td>
</tr>
<tr>
<td valign="top" width="30%">&#160;</td>
<td valign="top">const boost::property_tree::ptree&amp; server = config.get_child(&quot;server&quot;);</td>
</tr>
</tbody>
</table>
<p>Для доступа к элементу узла используются три метода:</p>
<table border="0" cellspacing="12" cellpadding="12" width="100%">
<tbody>
<tr>
<td valign="top" width="30%"><strong>get&lt;тип&gt;(&quot;имя_элемента&quot;)</strong></td>
<td valign="top">Позволяет получить значение элемента указанного типа, при отсутствии данного элемента будет выброшено исключение boost::property_tree::ptree_bad_path, при невозможности преобразования boost::property_tree::ptree_bad_data</td>
</tr>
<tr>
<td valign="top" width="30%">&#160;</td>
<td valign="top">server.get&lt;std::string&gt;(&quot;name&quot;)</td>
</tr>
<tr>
<td valign="top" width="30%"><strong>get(&quot;имя_элемента&quot;, значение_по_умолчанию)</strong></td>
<td valign="top">Если элемент не был найден, будет возвращено значение по умолчанию</td>
</tr>
<tr>
<td valign="top" width="30%">&#160;</td>
<td valign="top">server.get(&quot;port&quot;, 9000)</td>
</tr>
<tr>
<td valign="top" width="30%"><strong>get_optional&lt;тип&gt;(&quot;имя_элемента&quot;)</strong> </td>
<td valign="top">Будет возвращен тип boost::optional, таким образом мы можем узнать был ли данный элемент в файле или нет</td>
</tr>
<tr>
<td valign="top" width="30%">&#160;</td>
<td valign="top">if (const boost::optional&lt;std::string&gt; optionalComment = server.get_optional&lt;std::string&gt;(&quot;comment&quot;)) { &#8230; } </td>
</tr>
</tbody>
</table>
<p>Пример кода: </p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">try</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree</span><span style="color: #000040;">&amp;</span> server <span style="color: #000080;">=</span> config.<span style="color: #007788;">get_child</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;server&quot;</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: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>Server ===================================<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
		<span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Name:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> server.<span style="color: #007788;">get</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;name&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>
		<span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Port:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> server.<span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;port&quot;</span>, <span style="color: #0000dd;">9000</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #008080;">;</span>
	BOOST_FOREACH <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree</span><span style="color: #008080;">::</span><span style="color: #007788;">value_type</span><span style="color: #000040;">&amp;</span> channel, 
		config.<span style="color: #007788;">get_child</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;server.channels&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree</span><span style="color: #000040;">&amp;</span> values <span style="color: #000080;">=</span> channel.<span style="color: #007788;">second</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: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Channel --------------------------<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Name:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> values.<span style="color: #007788;">get</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;name&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Id:<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> values.<span style="color: #007788;">get</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">unsigned</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;id&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>
			<span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>Enabled:&quot;</span> <span style="color: #000080;">&lt;&lt;</span> values.<span style="color: #007788;">get</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">bool</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;enabled&quot;</span>, <span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">optional</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span> optionalComment <span style="color: #000080;">=</span> 
				values.<span style="color: #007788;">get_optional</span><span style="color: #000080;">&lt;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">string</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;comment&quot;</span><span style="color: #008000;">&#41;</span><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: #FF0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> <span style="color: #000080;">&lt;&lt;</span> optionalComment.<span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</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> boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree_bad_data</span><span style="color: #000040;">&amp;</span> error<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> error.<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> 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;">catch</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">property_tree</span><span style="color: #008080;">::</span><span style="color: #007788;">ptree_bad_path</span><span style="color: #000040;">&amp;</span> error<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> error.<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> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<h2>Запись конфигурации</h2>
<p>Теоретически можно создавать и редактировать конфигурационные файлы, для этого есть соответствующие методы:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="cpp" style="font-family:monospace;">config.<span style="color: #007788;">put</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;enabled&quot;</span>, <span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
write_xml<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;test.xml&quot;</span>, config<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>К сожалению практически в этом смысла мало:</p>
<ol>
<li>Файлы XML и JSON становятся трудночитаемыми человеком, так как полностью пропадает форматирование </li>
<li>UTF-8 фрагменты в JSON сохраняются с полной потерей информации </li>
<li>На этом фоне INFO смотрится прилично, но комментарии не сохраняются </li>
</ol>
<h2>Заключение</h2>
<p>У меня, как правило не стоит задача сохранения конфигураций из программы. Система конфигурируется человеком в текстовом редакторе, а программа данную конфигурацию читает и настраивает себя. Для этих целей библиотека очень удобна и действительно упрощает разбор конфигураций. В качестве формата файлов я выбрал JSON из-за его легкого синтаксиса и строгих проверок.</p>
<p>Для сохранений конфигураций библиотека, на мой взгляд пока не годится, разве что только файлы будут в формате INFO и вас устроит отсутствие комментариев.</p>
<p>Библиотека тяжеловата и поскольку представлена в виде заголовочных файлов, то компиляция замедлится.</p>
<h2>Файлы к заметке</h2>
<p><a href="http://www.devexp.ru/wp-content/uploads/2010/02/property_tree.zip" target="_blank">Архив с тестовой программой и конфигурацией</a> в формате INI, XML, JSON, INFO</p>
]]></content:encoded>
			<wfw:commentRss>http://www.devexp.ru/2010/02/chtenie-nastroek-prilozheniya/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.929 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2026-04-04 18:40:36 -->
<!-- mfunc W3TC_DYNAMIC_SECURITY --><!-- /mfunc W3TC_DYNAMIC_SECURITY -->