<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://mit.spbau.ru/sewiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Artem.sokolov</id>
		<title>SEWiki - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://mit.spbau.ru/sewiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Artem.sokolov"/>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Artem.sokolov"/>
		<updated>2026-05-03T08:09:16Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://mit.spbau.ru/sewiki/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Artem.sokolov&amp;diff=514</id>
		<title>Участник:Artem.sokolov</title>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Artem.sokolov&amp;diff=514"/>
				<updated>2011-10-02T17:31:48Z</updated>
		
		<summary type="html">&lt;p&gt;Artem.sokolov: Новая страница: «artem.a.sokolov@gmail.com»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;artem.a.sokolov@gmail.com&lt;/div&gt;</summary>
		<author><name>Artem.sokolov</name></author>	</entry>

	<entry>
		<id>http://mit.spbau.ru/sewiki/index.php?title=%D0%9D%D0%B0%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%BE_inline_%D0%B8_static._%D0%A1%D0%B8%D0%BD%D0%B3%D0%BB%D1%82%D0%BE%D0%BD.&amp;diff=346</id>
		<title>Напоминание про inline и static. Синглтон.</title>
		<link rel="alternate" type="text/html" href="http://mit.spbau.ru/sewiki/index.php?title=%D0%9D%D0%B0%D0%BF%D0%BE%D0%BC%D0%B8%D0%BD%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D1%80%D0%BE_inline_%D0%B8_static._%D0%A1%D0%B8%D0%BD%D0%B3%D0%BB%D1%82%D0%BE%D0%BD.&amp;diff=346"/>
				<updated>2011-05-31T16:10:31Z</updated>
		
		<summary type="html">&lt;p&gt;Artem.sokolov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Inline==&lt;br /&gt;
Рассмотрим некоторую inline функцию:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
inline void f() {}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Где ее разместить: в cpp или в header'e?'''&lt;br /&gt;
&lt;br /&gt;
1) При определении обычной функции в заголовочном файле может произойте так, что данный header включен в несколько cpp файлов.&lt;br /&gt;
Тогда при линковке произойдёт ошибка, т.к. функция имеет несколько определений. С inline функциями такой проблемы нет.&lt;br /&gt;
&lt;br /&gt;
2) Если вы создаете inline функцию, то ее нужно размещать в header'e, так как&lt;br /&gt;
* определение функции должно быть видно из того места в коде, где она используется;&lt;br /&gt;
* если разделить определение и тело inline функции, то ее можно будет использовать только в том cpp файле, в котором находится ее тело.&lt;br /&gt;
&lt;br /&gt;
Если определить метод внутри класса, то он автоматически становится inline:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class T {&lt;br /&gt;
    int size_;&lt;br /&gt;
public:&lt;br /&gt;
    size_t getSize() const { // inline!&lt;br /&gt;
        return size_;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Шаблонные функции - тоже inline, по очевидной причине: шаблонная функция должна быть определена к моменту вызова (при инстанциировании).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
template &amp;lt;typename T&amp;gt;&lt;br /&gt;
    void swap (T &amp;amp; a, T &amp;amp; b) {&lt;br /&gt;
        ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Глобальные переменные==&lt;br /&gt;
Что мы о них знаем? Что их не нужно использовать :), так как невозможно спрогнозировать, кто менял эту переменную, а значит и то значение, которое лежит в этой переменной.&lt;br /&gt;
Если у нас все же есть глобальная переменная и она определена в нескольких cpp файлах, то наша программа упадет при линковке. Избежать этого позволяет ключевое слово '''extern''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// 1.cpp&lt;br /&gt;
int i = 0;&lt;br /&gt;
&lt;br /&gt;
// 2.cpp&lt;br /&gt;
extern int i;    // extern указывает на то, что i определена где-то снаружи&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На самом деле, перед любым объявлением функции автоматически ставится extern (можно явно писать, ошибки не будет).&lt;br /&gt;
&lt;br /&gt;
==Статические переменные==&lt;br /&gt;
Если уж очень нужны глобальные переменные, лучше использовать статические переменные. Ключевое слово '''static''' обеспечивает защиту от перекрытия имен. Static может использоваться в 5 контекстах:&lt;br /&gt;
&lt;br /&gt;
'''1. Статические глобальные переменные'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// 1.cpp&lt;br /&gt;
static int i = 0;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Такое объявление переменной делает ее глобальной в пределах одного cpp файла, в данном случае - 1.cpp.&lt;br /&gt;
Если объявить статическую переменную i в заголовочном файле, то в каждом файле, в который будет подключен этот header, будет по одной собственной i.&lt;br /&gt;
&lt;br /&gt;
''Замечание: типы линковки.''&lt;br /&gt;
&lt;br /&gt;
Линковка бывает:&lt;br /&gt;
* external - функции и переменные между модулями;&lt;br /&gt;
* internal - внутри одного модуля. Пример использования - счетчик открытых файлов.&lt;br /&gt;
 &lt;br /&gt;
'''2. Статические функции'''&lt;br /&gt;
&lt;br /&gt;
Внутренняя линковка (internal). &lt;br /&gt;
&lt;br /&gt;
Можно создавать разные функции с одинаковыми сигнатурами. Так как они определяются во время вызова, то могут и встроиться :).&lt;br /&gt;
&lt;br /&gt;
Пример: можно в каждом cpp файле создать свою функцию static void test(). Напомню, что ключевое слово static защищает от конфликта имен.&lt;br /&gt;
&lt;br /&gt;
'''3. Статические локальные переменные'''&lt;br /&gt;
&lt;br /&gt;
Рассмотрим следующую функцию:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void print (double x) {&lt;br /&gt;
    static int i = 0;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; (++i) &amp;lt;&amp;lt; x &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Переменная i хранится не на стеке. По сути, она является глобальной переменной, но ее областью видимости является только функция print.&lt;br /&gt;
&lt;br /&gt;
Статические локальные переменные уничтожаются при выходе из main().&lt;br /&gt;
&lt;br /&gt;
Если сделать функцию print статической и вставить в несколько cpp файлов, то у каждого print будет свой счетчик i и своя реализация. А если сделать ее inline, то 1 общая реализация.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим еще один пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
1. void print (char const * fn, double x) {&lt;br /&gt;
2.     static int i = 0;&lt;br /&gt;
3.     static ofstream file(fn) = q(); // q() - некоторая функция&lt;br /&gt;
4.     file &amp;lt;&amp;lt; (++i) &amp;lt;&amp;lt; x &amp;lt;&amp;lt; endl;&lt;br /&gt;
5. }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Если бы переменная ofstream file не была статической, то при каждом входе в print файл открывался бы заново.&lt;br /&gt;
* Т.к. file - статическая, то при каждом входе в print, кроме первого раза, строка 3 игнорируется: как инициализация переменной file, так и =q(). &lt;br /&gt;
&lt;br /&gt;
Применение: хранение локальных данных функции.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
char * g() {&lt;br /&gt;
    static char m[100];&lt;br /&gt;
    return m; // имеет смысл, т.к. m static =&amp;gt; хранится не на стеке&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Статические переменные так же можно возвращать по ссылке:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
string &amp;amp; g() {&lt;br /&gt;
    static string s;&lt;br /&gt;
    return s;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Недостаток использования статических локальных переменных:''&lt;br /&gt;
* невозможно проследить, кто и когда их изменяет. В многопоточных приложениях от них вообще стоит отказаться :)&lt;br /&gt;
&lt;br /&gt;
Тем не менее, это эффективнее, чем выделение динамической памяти.&lt;br /&gt;
&lt;br /&gt;
'''4. Статические члены данных класса '''&lt;br /&gt;
&lt;br /&gt;
Вышесказанное относилось как к С++, так и к С. Этот и следующий параграфы, очевидно, относятся только к С++.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class Array {&lt;br /&gt;
private:&lt;br /&gt;
    static int count_;   // объявление статического члена данных класса. Он не хранится в объекте класса.&lt;br /&gt;
    static string name_; // Статические члены данных класса подобны глобальным переменным внутри класса. &lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В данном примере статические члены данных объявлены private, поэтому изменять их можно только из внутренних методов класса или &amp;quot;друзьями&amp;quot; (friend).&lt;br /&gt;
Для того, чтобы проинициализировать статические члены данных, их нужно определить в каком-нибудь срр-файле, чтобы выделилась память:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
Array::count_ = 0;&lt;br /&gt;
string Array::name_(&amp;quot;Array&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определить статическое поле прямо внутри класса можно тогда и только тогда, когда оно целочисленное и константное (т.к. в момент компиляции работа только с целочисленными типами):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static int const dimension = 10;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Примеры использования:''&lt;br /&gt;
* подсчет количества экземпляров класса;&lt;br /&gt;
* хранение информации, общей для всех экземпляров класса;&lt;br /&gt;
* хранение списка объектов класса.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''5. Статические методы класса'''&lt;br /&gt;
&lt;br /&gt;
Не зависят от объектов класса. Рассмотрим пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class Array {&lt;br /&gt;
private:&lt;br /&gt;
     static string name_;&lt;br /&gt;
public:&lt;br /&gt;
     static string getName() { // rem. getName() - inline, т.к. определена внутри класса &lt;br /&gt;
         return name_;&lt;br /&gt;
     }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    Array a;&lt;br /&gt;
    a.getName();      // cинтаксически возможно, но логически неправильно&lt;br /&gt;
&lt;br /&gt;
    Array::getName(); // правильно&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Метод getName() не имеет доступа к членам класса, но если передать в нее ссылку на объект класса, то из getName() можно будет изменять private поля.&lt;br /&gt;
&lt;br /&gt;
Невозможно объявить статический метод класса константным, так как const запрещает изменять поля объекта, а в static методы this не передается:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static void f() const; // ошибка!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''template и static'''&lt;br /&gt;
&lt;br /&gt;
* Поведение статических локальных переменных в шаблонах функций: для каждого инстанса функции будет своя статическая локальная переменная.&lt;br /&gt;
* Static в шаблонах классов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
template &amp;lt;class T&amp;gt; &lt;br /&gt;
    class Array {};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для каждого инстанса класса будут свои статические поля и методы. &lt;br /&gt;
&lt;br /&gt;
Но как определить снаружи статическую переменную шаблонного класса?&lt;br /&gt;
&lt;br /&gt;
1 вариант:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// array.h&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
    class Array &lt;br /&gt;
{&lt;br /&gt;
    static double q;&lt;br /&gt;
public:&lt;br /&gt;
    Array();&lt;br /&gt;
    static double getQ() { &lt;br /&gt;
        return q;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
    double Array&amp;lt;T&amp;gt;::q = 1.5;&lt;br /&gt;
&lt;br /&gt;
// main.cpp&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;array.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; Array&amp;lt;int&amp;gt;::getQ() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; Array&amp;lt;float&amp;gt;::getQ() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//output: 1.5, 1.5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2 вариант:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// array.h&lt;br /&gt;
template &amp;lt;class T&amp;gt;&lt;br /&gt;
    class Array &lt;br /&gt;
{&lt;br /&gt;
    static double q;&lt;br /&gt;
public:&lt;br /&gt;
    Array();&lt;br /&gt;
    static double getQ() { &lt;br /&gt;
        return q;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//array.cpp&lt;br /&gt;
#include &amp;quot;array.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
template &amp;lt;&amp;gt;&lt;br /&gt;
        double Array&amp;lt;int&amp;gt;::q = 1.5;&lt;br /&gt;
template &amp;lt;&amp;gt;&lt;br /&gt;
        double Array&amp;lt;float&amp;gt;::q = 2.6;&lt;br /&gt;
&lt;br /&gt;
// main.cpp&lt;br /&gt;
#include &amp;lt;iostream&amp;gt;&lt;br /&gt;
#include &amp;quot;array.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; Array&amp;lt;int&amp;gt;::getQ() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    std::cout &amp;lt;&amp;lt; Array&amp;lt;float&amp;gt;::getQ() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// output: 1.5, 2.6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB. Вообще, шаблоны не очень дружат со static параметром шаблона: не может быть указателя на статическую функцию.&lt;br /&gt;
&lt;br /&gt;
==Синглтон==&lt;br /&gt;
&lt;br /&gt;
def. Синглтон - это объект, который в момент исполнения существует в единственном экземпляре.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
// array.h&lt;br /&gt;
struct Array {&lt;br /&gt;
private:&lt;br /&gt;
    // все конструкторы&lt;br /&gt;
    static Array * inst_;&lt;br /&gt;
public:&lt;br /&gt;
    static Array &amp;amp; getInstance() {&lt;br /&gt;
        if (inst_ == 0)&lt;br /&gt;
            inst_ = new Array();&lt;br /&gt;
        return *inst_;&lt;br /&gt;
    }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// array.cpp&lt;br /&gt;
Array * Array::inst_ = 0;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Artem.sokolov</name></author>	</entry>

	</feed>