mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-11-26 20:34:32 +03:00
Update ru-ru/c++-ru.html.markdown
This commit is contained in:
parent
8abfffd183
commit
0aaa5a232c
@ -21,7 +21,7 @@ C++ - компилируемый, статически типизированн
|
||||
- язык с поддержкой обобщенного программирования
|
||||
|
||||
Хотя его синтаксис может показаться более трудным или сложным для понимания, чем в более современных языках,
|
||||
он широко применяется т.к. код написанный на C++ компилируется в набор инструкций, которые могут быть выполнены напрямую
|
||||
он широко применяется, так как код, написанный на C++, компилируется в набор инструкций, которые могут быть выполнены напрямую
|
||||
процессором. C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков
|
||||
программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов
|
||||
устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр).
|
||||
@ -34,21 +34,21 @@ C++ - компилируемый, статически типизированн
|
||||
// C++ практически представляет собой надмножество C и имеет схожий синтаксис
|
||||
// для объявления переменных, примитивов и функций.
|
||||
|
||||
// Также как и в С, точкой входа в программу является функция с именем main,
|
||||
// Так же, как и в С, точкой входа в программу является функция с именем main,
|
||||
// которая возвращает целочисленное значение.
|
||||
// Это значение является кодом ответа программы.
|
||||
// Смотрите https://goo.gl/JYGKyv для более подробной информации.
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Аргументы командной строки переданные в программу хранятся в переменных
|
||||
// argc и argv, также как и в C.
|
||||
// Аргументы командной строки, переданные в программу, хранятся в переменных
|
||||
// argc и argv, так же, как и в C.
|
||||
// argc указывает на количество аргументов,
|
||||
// а argv является масивом C-подобных строк (char*), который непосредсвенно
|
||||
// а argv является массивом C-подобных строк (char*), который непосредсвенно
|
||||
// содержит аргументы.
|
||||
// Первым аргументом всегда передается имя программы.
|
||||
// argc и argv могут быть опущены если вы не планируете работать с аругментамы
|
||||
// argc и argv могут быть опущены, если вы не планируете работать с аругментами
|
||||
// коммандной строки.
|
||||
// Тогда сигнатура функции будет иметь следующий вид int main()
|
||||
// Тогда сигнатура функции будет иметь следующий вид: int main()
|
||||
|
||||
// Возвращаемое значение 0 указывает на успешное завершение программы.
|
||||
return 0;
|
||||
@ -56,17 +56,17 @@ int main(int argc, char** argv)
|
||||
|
||||
// Тем не менее, C++ имеет свои отличия:
|
||||
|
||||
// В C++, символьные литералы являются символами.
|
||||
// В C++ символьные литералы имеют тип char.
|
||||
sizeof('c') == sizeof(char) == 1
|
||||
|
||||
// В С, символьные литералы - целые числа.
|
||||
// В C символьные литералы - целые числа.
|
||||
sizeof('c') == sizeof(int)
|
||||
|
||||
|
||||
// C++ имеет строго прототипирование.
|
||||
// C++ имеет строгое прототипирование.
|
||||
void func(); // функция, которая не принимает аргументов.
|
||||
|
||||
// In C
|
||||
// В языке C
|
||||
void func(); // функция, которая может принять сколько угодно аргументов.
|
||||
|
||||
// Использование nullptr вместо NULL в C++.
|
||||
@ -124,7 +124,7 @@ int main()
|
||||
doSomethingWithInts(20, 5); // a = 20, b = 5
|
||||
}
|
||||
|
||||
// Аргументы по умолчанию должен быть в конце списка аргументов.
|
||||
// Аргументы по умолчанию должны быть в конце списка аргументов.
|
||||
|
||||
void invalidDeclaration(int a = 1, int b) // Ошибка!
|
||||
{
|
||||
@ -162,9 +162,9 @@ void foo()
|
||||
|
||||
int main()
|
||||
{
|
||||
// Включает все функци с пространства имен Second в текущую область видимости.
|
||||
// Включает все функци из пространства имен Second в текущую область видимости.
|
||||
// Обратите внимание, что простой вызов foo() больше не работает,
|
||||
// так как теперь не ясно вызываем ли мы foo с пространства имен Second или
|
||||
// так как теперь не ясно, вызываем ли мы foo из пространства имен Second, или
|
||||
// из глобальной области видимости.
|
||||
using namespace Second;
|
||||
|
||||
@ -174,11 +174,11 @@ int main()
|
||||
}
|
||||
|
||||
///////////////
|
||||
// Ввод/Вывод
|
||||
// Ввод и вывод
|
||||
///////////////
|
||||
|
||||
// Вводи и вывод в C++ использует потоки
|
||||
// cin, cout и cerr предоставлнеы методами stdin, stdout и stderr.
|
||||
// Ввод и вывод в C++ использует потоки
|
||||
// cin, cout и cerr представляют потоки stdin, stdout и stderr.
|
||||
// << - оператор вставки, >> - оператор извлечения.
|
||||
|
||||
#include <iostream> // Включение файла для работы с потоками Ввода\Вывода.
|
||||
@ -189,7 +189,7 @@ int main()
|
||||
{
|
||||
int myInt;
|
||||
|
||||
// Выводит stdout (или терминал\экран)
|
||||
// Выводит в stdout (или в терминал/на экран)
|
||||
cout << "Enter your favorite number:\n";
|
||||
// Принимает ввод
|
||||
cin >> myInt;
|
||||
@ -208,7 +208,7 @@ int main()
|
||||
// Строки в C++ являются объектами и имеют много функций-членов.
|
||||
#include <string>
|
||||
|
||||
using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотек)
|
||||
using namespace std; // Строки также доступны в пространстве имен std (стандартная библиотека)
|
||||
|
||||
string myString = "Hello";
|
||||
string myOtherString = " World";
|
||||
@ -227,7 +227,7 @@ cout << myString; // "Hello Dog"
|
||||
// Ссылки
|
||||
/////////////
|
||||
|
||||
// В добавок к указателям доступных в C,
|
||||
// Кроме указателей, доступных в C,
|
||||
// C++ имеет _ссылки_.
|
||||
// Это такой тип указателя, который не может быть переназначен после инициализации
|
||||
// и не может иметь значения null.
|
||||
@ -241,11 +241,11 @@ string foo = "I am foo";
|
||||
string bar = "I am bar";
|
||||
|
||||
|
||||
string& fooRef = foo; // Здесь создается указатель на foo.
|
||||
string& fooRef = foo; // Здесь создается ссылка на foo.
|
||||
fooRef += ". Hi!"; // Изменяет foo по ссылке
|
||||
cout << fooRef; // Печатает "I am foo. Hi!"
|
||||
|
||||
// Не переназначает "fooRef". Это тоже самое как "foo = bar", и
|
||||
// Не переназначает "fooRef". Это то же самое, что и "foo = bar", и
|
||||
// foo == "I am bar"
|
||||
// после этой строчки.
|
||||
cout << &fooRef << endl; // Печатает адрес foo
|
||||
@ -256,31 +256,31 @@ cout << fooRef; // Печатает "I am bar"
|
||||
// Адрес fooRef остается тем же, то есть он по-прежнему ссылается на foo.
|
||||
|
||||
|
||||
const string& barRef = bar; // Создает const со ссылкой на bar.
|
||||
// Также как и C, значения const (и указателей и ссылок) не могут быть изменены.
|
||||
barRef += ". Hi!"; // Ошибка, указатель const не может быть изменен.
|
||||
const string& barRef = bar; // Создает константную ссылку.
|
||||
// Так же, как и в C, константные значения (а также указатели и ссылки) не могут быть изменены.
|
||||
barRef += ". Hi!"; // Ошибка, константная ссылка не может быть изменена.
|
||||
|
||||
// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомится
|
||||
// с концепцией известной как "временный объект". Представьте, что мы имеем следующий код
|
||||
// Обходной путь: Прежде чем мы рассмотрим указатели более детально, нам нужно ознакомиться
|
||||
// с концепцией, известной как "временный объект". Представьте, что мы имеем следующий код
|
||||
string tempObjectFun() { ... }
|
||||
string retVal = tempObjectFun();
|
||||
|
||||
// Вот что на самом деле происходит во второй строе:
|
||||
// Вот что на самом деле происходит во второй строке:
|
||||
// - tempObjectFun возвращает строковый объект
|
||||
// - с возвращаемого объекта создается новая строка в качестве аргумента конструктору
|
||||
// - из возвращаемого объекта создается новая строка в качестве аргумента конструктору
|
||||
// - возвращаемый объект уничтожается
|
||||
// Возвращаемый объект называется временным объектом. Временные объекты создаются
|
||||
// Возвращаемый объект называется временным объектом. Временные объекты создаются,
|
||||
// когда функция возвращает объект, и уничтожаются в конце выполнения обрамляющего
|
||||
// выражения (По крайней мере, так это описывает спецификация, хотя компиляторы могут
|
||||
// изменять это поведение. Для более подробной информации смотрите "оптимизация
|
||||
// возвращаемого значения". Таким образом в этом коде:
|
||||
// возвращаемого значения".) Таким образом в этом коде:
|
||||
foo(bar(tempObjectFun()))
|
||||
|
||||
// предполагая, что foo и bar существуют, объект возвращаемый tempObjectFun передается
|
||||
// предполагая, что foo и bar существуют, объект, возвращаемый tempObjectFun, передается
|
||||
// в bar, и уничтожается перед вызовом foo.
|
||||
|
||||
// Возвращаемся к указателям. Исключением для правила "в конце выполнения обрамляющего
|
||||
// выражения" является временный объект привязанный к ссылке const, в этом случае
|
||||
// выражения" является временный объект, привязанный к ссылке const, в этом случае
|
||||
// его жизненный цикл продлевается до текущей области видимости:
|
||||
|
||||
void constReferenceTempObjectFun() {
|
||||
@ -290,7 +290,7 @@ void constReferenceTempObjectFun() {
|
||||
}
|
||||
|
||||
// В C++11 предоставлен еще один тип ссылок специально для временных объектов.
|
||||
// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет в
|
||||
// objects. Вы не можете объявить переменную этого типа, но он имеет приоритет
|
||||
// в резолюции перегрузки:
|
||||
|
||||
void someFun(string& s) { ... } // Обычная ссылка
|
||||
@ -304,7 +304,7 @@ someFun(tempObjectFun()); // Выполняет версию с временн
|
||||
basic_string(const basic_string& other);
|
||||
basic_string(basic_string&& other);
|
||||
|
||||
// Идея в том, если мы конструируем новую строку из временного объекта (который
|
||||
// Идея в том, что если мы конструируем новую строку из временного объекта (который
|
||||
// так или иначе будет уничтожен), мы можем использовать более эффективный конструктор,
|
||||
// который "спасает" части этой временной строки. Эта концепция была названа
|
||||
// "move semantics".
|
||||
@ -313,7 +313,7 @@ basic_string(basic_string&& other);
|
||||
// Перечисления
|
||||
/////////////////////
|
||||
|
||||
// Перечисления - способ объявления констант и установки их значений в основном
|
||||
// Перечисления - способ объявления констант и установки их значений, в основном
|
||||
// использующийся для упрощения чтения кода.
|
||||
enum ECarTypes
|
||||
{
|
||||
@ -346,7 +346,7 @@ void WriteByteToFile(uint8_t InputValue)
|
||||
|
||||
void WritePreferredCarTypeToFile(ECarTypes InputCarType)
|
||||
{
|
||||
// Перечисление неявно преобразуется в uint8_t из-за раннее объявленного
|
||||
// Перечисление неявно преобразуется в uint8_t из-за ранее объявленного
|
||||
// типа перечисления.
|
||||
WriteByteToFile(InputCarType);
|
||||
}
|
||||
@ -384,7 +384,7 @@ void WritePreferredCarTypeToFile(ECarTypes InputCarType)
|
||||
// Объявление класса.
|
||||
// Обычно классы объявляют в заголовочном (.h или .hpp) файле.
|
||||
class Dog {
|
||||
// Переменный-члены и функции являются частными по умолчанию.
|
||||
// Переменные-члены и функции являются приватными по умолчанию.
|
||||
std::string name;
|
||||
int weight;
|
||||
|
||||
@ -406,27 +406,26 @@ public:
|
||||
|
||||
// Функции, которые не изменяют состояние объекта,
|
||||
// должны быть помечены как const.
|
||||
// Это позволяет вызывать их если дана const ссылка на объект.
|
||||
// Обратите внимание, функции должны быть явно объявлены как _virtual_
|
||||
// Это позволяет вызывать их, если дана const ссылка на объект.
|
||||
// Обратите внимание, функции должны быть явно объявлены как _virtual_,
|
||||
// если вы хотите перегрузить их в производных классах.
|
||||
// Функции не являются виртуальными по умолчания для повышения производительности.
|
||||
// Функции не являются виртуальными по умолчанию для повышения производительности.
|
||||
virtual void print() const;
|
||||
|
||||
// Такде функции могут быть определены внутри тела класса.
|
||||
// Также функции могут быть определены внутри тела класса.
|
||||
// Функции, определенные следующим образом, автоматически встроены.
|
||||
void bark() const { std::cout << name << " barks!\n"; }
|
||||
|
||||
// Наряду с конструкторами, в C++ есть деструкторы.
|
||||
// Они вызываются, когда объект удаляется или выпадает с области видимости.
|
||||
// Это активирует мощную парадигму программирования известную как RAII
|
||||
// Они вызываются, когда объект удаляется или выпадает из области видимости.
|
||||
// Это активирует мощную парадигму программирования, известную как RAII
|
||||
// (смотрите ниже)
|
||||
// Деструктор должен быть виртуальным, если класс будет производным.
|
||||
// Если он не виртуальный, тогда деструктор производного класса не будет вызван
|
||||
// Если он не виртуальный, тогда деструктор производного класса не будет вызван,
|
||||
// если объект удален по ссылке или указателю базового класса.
|
||||
// or pointer.
|
||||
virtual ~Dog();
|
||||
|
||||
}; // Определение класса должно завершатся точкой с запятой.
|
||||
}; // Определение класса должно завершаться точкой с запятой.
|
||||
|
||||
// Функции-члены класса, как правило, реализуются в .cpp файлах.
|
||||
Dog::Dog()
|
||||
@ -468,7 +467,7 @@ int main() {
|
||||
// Интерфейсы:
|
||||
|
||||
// Этот класс наследует все открытые и защищенные члены класса Dog
|
||||
// также как и все закрытые, но не может непосредственно получить доступ к закрытым
|
||||
// так же, как и все закрытые, но не может непосредственно получить доступ к закрытым
|
||||
// членам\методам без открытых или защищенных методов для этого.
|
||||
class OwnedDog : public Dog {
|
||||
|
||||
@ -477,7 +476,7 @@ class OwnedDog : public Dog {
|
||||
// Переопределяем поведение функции печати для всех OwnedDog. Смотрите
|
||||
// https://goo.gl/3kuH2x для боле общего введения, если вы не знакомы
|
||||
// с концепцией полиморфизма подтипов (включения).
|
||||
// Ключевое слово override является необязательным, но указывает что метод
|
||||
// Ключевое слово override является необязательным, но указывает, что метод
|
||||
// на самом деле перегружается в базовом классе.
|
||||
void print() const override;
|
||||
|
||||
@ -527,9 +526,9 @@ public:
|
||||
Point (double a, double b) :
|
||||
x(a),
|
||||
y(b)
|
||||
{ /* Ничего не делайте кроме инициализации значений */ }
|
||||
{ /* Ничего не делайте, кроме инициализации значений */ }
|
||||
|
||||
// Перегружаем оперот +.
|
||||
// Перегружаем оператор +.
|
||||
Point operator+(const Point& rhs) const;
|
||||
|
||||
// Перегружаем оператор +=.
|
||||
@ -568,9 +567,9 @@ int main () {
|
||||
/////////////////////
|
||||
|
||||
// Шаблоны в С++, в основном, используются для обобщенного программирования, хотя
|
||||
// они гораздо более мощны чем дженерики в других языках. Они также поддерживают
|
||||
// они гораздо более мощны, чем дженерики в других языках. Они также поддерживают
|
||||
// явные, частные и функциональные типы классов; на самом деле, они являются
|
||||
// тьюринг-полным языком встроенным в C++!
|
||||
// тьюринг-полным языком, встроенным в C++!
|
||||
|
||||
// Мы начнем с наиболее распространенного типа обобщенного программирования. Чтобы
|
||||
// определить класс или функцию, которая принимает параметр типа:
|
||||
@ -581,9 +580,9 @@ public:
|
||||
void insert(const T&) { ... }
|
||||
};
|
||||
|
||||
// Во время компиляции, компилятор фактически генерирует копии каждого шаблона
|
||||
// с замещенными параметрами, по-этому полное определение класса должно присутствовать
|
||||
// при каждом вызове. Именно по-этому классы шаблонов полностью определены в
|
||||
// Во время компиляции компилятор фактически генерирует копии каждого шаблона
|
||||
// с замещенными параметрами, поэтому полное определение класса должно присутствовать
|
||||
// при каждом вызове. Именно поэтому классы шаблонов полностью определены в
|
||||
// заголовочных файлах.
|
||||
|
||||
// Чтобы создать экземпляр класса шаблона на стеке:
|
||||
@ -597,11 +596,11 @@ Box<Box<int> > boxOfBox;
|
||||
boxOfBox.insert(intBox);
|
||||
|
||||
// Вплоть до С++11, вы должны были ставить пробел между двумя символами '>', иначе '>>'
|
||||
// принимался парсером, как оператор правого сдвига.
|
||||
// принимался парсером, как оператор сдвига вправо.
|
||||
|
||||
// Иногда вы можете увидеть
|
||||
// template<typename T>
|
||||
// вместо этого. В этом случае, ключевые слова 'class' и 'typename' _в основном_
|
||||
// вместо этого. В этом случае ключевые слова 'class' и 'typename' _в основном_
|
||||
// взаимозаменяемыми. Для более подробной информации смотрите
|
||||
// http://en.wikipedia.org/wiki/Typename
|
||||
// (да-да, это ключевое слово имеет собственную страничку на вики).
|
||||
@ -616,11 +615,11 @@ void barkThreeTimes(const T& input)
|
||||
}
|
||||
|
||||
// Обратите внимание, что здесь ничего не указано о типе параметра. Компилятор
|
||||
// будет генерировать и затем проверять тип каждый вызов шаблона, по-этому
|
||||
// будет генерировать и затем проверять на тип каждый вызов шаблона, поэтому
|
||||
// данная функция работает с любым типом 'T', который имеет метод 'bark'.
|
||||
|
||||
Dog fluffy;
|
||||
fluffy.setName("Fluffy")
|
||||
fluffy.setName("Fluffy");
|
||||
barkThreeTimes(fluffy); // Печатает "Fluffy barks" три раза.
|
||||
|
||||
//Параметры шаблона не должны быть классами:
|
||||
@ -652,20 +651,20 @@ printMessage<10>(); // Печатает "Learn C++ faster in only 10 minutes!"
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
// Все исключения брошены внутри блока _try_ могут быть пойманы в последующем блоке
|
||||
// Все исключения, брошенные в блоке _try_ могут быть пойманы в последующем блоке
|
||||
// _catch_.
|
||||
try {
|
||||
// Не выделяйте память в куче для исключений с помощью ключевого слова _new_.
|
||||
throw std::runtime_error("A problem occurred");
|
||||
}
|
||||
|
||||
// Поймайте исключение по константной ссылке, если они являются объектами
|
||||
// Поймайте исключение по константной ссылке, если оно является объектом
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
std::cout << ex.what();
|
||||
}
|
||||
|
||||
// Ловит любое исключение не пойманное предыдущим блоком _catch_
|
||||
// Ловит любое исключение, не пойманное предыдущим блоком _catch_
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Unknown exception caught";
|
||||
@ -681,7 +680,7 @@ catch (...)
|
||||
// некоторого ресурса неразрывно совмещается с инициализацией, а освобождение -
|
||||
// с уничтожением объекта.
|
||||
|
||||
// Чтобы понять на сколько это полезно,
|
||||
// Чтобы понять, на сколько это полезно,
|
||||
// рассмотрим функцию, которая использует обработчик файлов в С:
|
||||
void doSomethingWithAFile(const char* filename)
|
||||
{
|
||||
@ -695,31 +694,31 @@ void doSomethingWithAFile(const char* filename)
|
||||
fclose(fh); // Закрываем обработчик файла.
|
||||
}
|
||||
|
||||
// К сожалению, вещи быстро осложняется обработкой ошибок.
|
||||
// Предположим fopen может потерпеть неудачу, тогда doSomethingWithTheFile и
|
||||
// doSomethingElseWithIt вернут коды ошибок если потерпят неудачу.
|
||||
// К сожалению, вещи быстро осложняются обработкой ошибок.
|
||||
// Предположим, fopen может потерпеть неудачу, тогда doSomethingWithTheFile и
|
||||
// doSomethingElseWithIt вернут коды ошибок, если потерпят неудачу.
|
||||
// (Исключения являются предпочтительным способом обработки ошибок,
|
||||
// но некоторые программисты, особенно те, кто имеет большой опыт работы с С,
|
||||
// не согласны с аргументами о полезности исключений).
|
||||
// Теперь мы должны проверить каждый вызов на наличие ошибок и закрыть обработчик
|
||||
// файла если таковы есть.
|
||||
// файла, если он есть.
|
||||
bool doSomethingWithAFile(const char* filename)
|
||||
{
|
||||
FILE* fh = fopen(filename, "r"); // Открывает файл в режиме чтения
|
||||
if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает null.
|
||||
return false; // Сообщает об неудаче вызывающему.
|
||||
if (fh == nullptr) // В случае неудачи возвращаемый указатель принимает значение null.
|
||||
return false; // Сообщает о неудаче вызывающему.
|
||||
|
||||
// Предположим, каждая функция возвращает false в случае неудачи
|
||||
if (!doSomethingWithTheFile(fh)) {
|
||||
fclose(fh); // Закрываем обработчик файл чтобы не было утечек
|
||||
fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
|
||||
return false; // Сообщает об ошибке.
|
||||
}
|
||||
if (!doSomethingElseWithIt(fh)) {
|
||||
fclose(fh); // Закрываем обработчик файл чтобы не было утечек
|
||||
fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
|
||||
return false; // Сообщает об ошибке.
|
||||
}
|
||||
|
||||
fclose(fh); // Закрываем обработчик файл чтобы не было утечек
|
||||
fclose(fh); // Закрываем обработчик файла, чтобы не было утечек
|
||||
return true; // Указывает на успех
|
||||
}
|
||||
|
||||
@ -736,7 +735,7 @@ bool doSomethingWithAFile(const char* filename)
|
||||
if (!doSomethingElseWithIt(fh))
|
||||
goto failure;
|
||||
|
||||
fclose(fh); // Close the file
|
||||
fclose(fh); // Закрываем файл.
|
||||
return true; // Указывает на успех
|
||||
|
||||
failure:
|
||||
@ -761,12 +760,12 @@ void doSomethingWithAFile(const char* filename)
|
||||
throw; // Затем повторно бросает исключение.
|
||||
}
|
||||
|
||||
fclose(fh); // Close the file
|
||||
fclose(fh); // Закрываем файл.
|
||||
// Успех
|
||||
}
|
||||
|
||||
// Сравните это с использованием класса потока файла (fstream) в С++, который
|
||||
// использует свой деструктор чтобы закрыть файл. Еще раз взгляните выше,
|
||||
// использует свой деструктор, чтобы закрыть файл. Еще раз взгляните выше,
|
||||
// деструктор вызывается автоматически, когда объект выпадает из области видимости.
|
||||
void doSomethingWithAFile(const std::string& filename)
|
||||
{
|
||||
@ -781,26 +780,26 @@ void doSomethingWithAFile(const std::string& filename)
|
||||
|
||||
// Это имеет _огромнейшие_ преимущества:
|
||||
// 1. Неважно, что произойдет,
|
||||
// ресурсы (в данном случае обработчик файлов) будут очищены.
|
||||
// После того, как вы правильно напишите деструктор,
|
||||
// Больше будет _не возможно_ закрыть обработчик файлов или допустить утечку.
|
||||
// ресурсы (в данном случае дескриптор файла) будут очищены.
|
||||
// После того, как вы правильно напишете деструктор,
|
||||
// Больше будет _невозможно_ закрыть обработчик файлов или допустить утечку.
|
||||
// 2. Обратите внимание, что код намного проще.
|
||||
// Деструктор закрывает файловый поток "за кулисами" и вам больше не нужно об
|
||||
// этом беспокоится.
|
||||
// Деструктор закрывает файловый поток "за кулисами", и вам больше не нужно об
|
||||
// этом беспокоиться.
|
||||
// 3. Код устойчив к исключениям.
|
||||
// Исключение может быть брошено в любом месте в функции и это никак не повлияет
|
||||
// Исключение может быть брошено в любом месте в функции, и это никак не повлияет
|
||||
// на очистку.
|
||||
|
||||
// Весь идиоматический код на С++ широко использует RAII для всех ресурсов.
|
||||
// Дополнительные примеры включат
|
||||
// Дополнительные примеры включат:
|
||||
// - Использование памяти unique_ptr и shared_ptr
|
||||
// - Контейнеры - стандартная библиотека связанных списков, векторы
|
||||
// (т.е. самоизменяемые массивы), хэш-карты и все остальное автоматически
|
||||
// уничтожается сразу-же, когда выходит за пределы области видимости.
|
||||
// - Ипользование мютексов lock_guard и unique_lock
|
||||
// (т.е. самоизменяемые массивы), хэш-таблицы и все остальное автоматически
|
||||
// уничтожается сразу же, когда выходит за пределы области видимости.
|
||||
// - Ипользование мьютексов lock_guard и unique_lock
|
||||
|
||||
// Контейнеры с пользовательскими классами в качестве ключей требуют
|
||||
// функций-компаратор в самом объекте или как указатель на функцию. Примитивы
|
||||
// сравнивающих функций в самом объекте или как указатель на функцию. Примитивы
|
||||
// имеют компараторы по умолчанию, но вы можете перегрузить их.
|
||||
class Foo {
|
||||
public:
|
||||
@ -822,7 +821,7 @@ fooMap.find(Foo(1)); //true
|
||||
// Веселые вещи
|
||||
/////////////////////
|
||||
|
||||
// Аспекты С++, которые могут быть удивительными для новичком (и даже для некоторых
|
||||
// Аспекты С++, которые могут быть удивительными для новичков (и даже для некоторых
|
||||
// ветеранов). Этот раздел, к сожалению, очень неполон. С++ является одним из самых
|
||||
// простых языков, где очень легко выстрелить себе в ногу.
|
||||
|
||||
@ -838,7 +837,7 @@ class FooSub : public Foo {
|
||||
// 0 == false == NULL (в основном)!
|
||||
bool* pt = new bool;
|
||||
*pt = 0; // Устанавливает значение указателя 'pt' в false.
|
||||
pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе линии проходят
|
||||
pt = 0; // Устанавливает значение 'pt' в нулевой указатель. Обе строки проходят
|
||||
// компиляцию без ошибок.
|
||||
|
||||
// nullptr приходит на помощь:
|
||||
@ -875,17 +874,17 @@ vector<Foo> v;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
v.push_back(Foo());
|
||||
|
||||
// В слудующей точке размер v устанавливается в 0, но деструктор не вызывается
|
||||
// В следующей точке размер v устанавливается в 0, но деструктор не вызывается
|
||||
// и не происходит очистка ресурсов!
|
||||
v.empty();
|
||||
v.push_back(Foo()); // Новые значения копируются в первый вставленный Foo
|
||||
|
||||
// Настоящие уничтожение всех значений v. Смотрите раздел о временном объекте
|
||||
// Настоящее уничтожение всех значений v. Смотрите раздел о временном объекте
|
||||
// для объяснения того, как это работает.
|
||||
v.swap(vector<Foo>());
|
||||
|
||||
```
|
||||
Дальнейшее чтение:
|
||||
## Дальнейшее чтение:
|
||||
|
||||
Наиболее полное и обновленное руководство по С++ можно найти на
|
||||
<http://cppreference.com/w/cpp>
|
||||
|
Loading…
Reference in New Issue
Block a user