Использование набора вместе с отображением

В некоторых случаях приходится выбирать целый комплект элементов отображения. Для этого пригодится комплект ключей к этому отображению:

Set keys = mapOfIntegers.keySet(); Logger l = Logger.getLogger(Test); for (String key : keys) { Integer value = mapOfIntegers.get(key); l.info(Value keyed by ‘ + key + ‘ is ‘ + value + ‘); }

Обратите внимание, что при применении вызова Logger способ toString() класса Integer, извлекаемый изотображения, вызывается машинально. Отображение не возвращает перечня собственных ключей, в силу того, что любой ключ неповторим, а уникальность – показатель комплекта.

Функционал java коллекций

Отображения (ассоциативные массивы)

  • Map — интерфейс отображений;
  • SortedMap — расширение Map с возможностью автоматической сортировки ключей;
  • NavigableMap — расширение не сильный с приблизительным доступом к элементу. К примеру, higherKey возвращает мельчайший ключ, что больше указанного;
  • HashMap — класс реализующий отображение. null значение не запрещаеться в качестве элемента и ключа. Без синхронизации;
  • Hashtable — класс реализующий отображение. null значения запрещены. С помощью синхронизации;
  • LinkedHashMap — расширение HashMap, содержит в себе связанный перечень для хранения элементов в порядке добавления, эргономичен в кэшировании данных;
  • WeakHashMap — специальное отображение, применяющее в качестве значений не сильный ссылки. Удобен для кэширования неизменяемых объектов. Без синхронизации.
  • TreeMap — реализация интерфейса SortedMap, представляет собой красно-тёмное дерево. Без синхронизации;
  • EnumMap — специальное отображение, применяющее в качестве ключа перечисление. Без синхронизации. (java 5+)
  • IdentityHashMap — редко применяемая реализация отображения, проверка значения ключа делается через операцию ==, а не способ equal как в большинстве случаев. Без синхронизации.
  • Map.Entry — интерфейс для пары ключ/значение, возможно взять из итератора;

Перечни

Перечень представляет собой упорядоченную коллекция. Имеется доступ к элементам по индексу. Может содержать однообразные элементы.

  • List — расширение Collection для управления упорядоченными коллекциями;
  • ArrayList — простой динамический массив. Без синхронизации;
  • Vector — динамический массив с синхронизацией, соответственно чуть медленей;
  • LinkedList — связной перечень. Без синхронизации. Более действен при нередких вставках/удалений элементов в середине, чем ArrayList/Vector. Употребляется как стек, очередь, двунаправленная очередь;
  • Stack — расширение Vector для реализации стека;

Очередь/стек

  • Queue — интерфейс для управления очередью (java 5+);
  • Deque — расширение Queue для управления двунаправленной очередью (java 6+);
  • ArrayDeque — оптимизированная очереди и реализация стека на базе интерфейса Deque (стремительнее Stack и LinkedList). Без синхронизации. (java 5+);
  • LinkedList — связной перечень, в последних предположениях добавлена реализация интерфейсов Queue и Deque;
  • PriorityQueue — приоритетная очередь, т.е. элементы смогут размешаться в соответствии с указанным методом сравнения (класс Comparator). (java 5+);

Множество

Множество является коллекцией не имеющей однообразных элементов.

  • Set — интерфейс для управления множеством;
  • SortedSet — интерфейс для упорядоченного множества;
  • NavigableSet — расширение SortedSet с приблизительным доступом к элементу. К примеру, способ higher дает возможность приобрести мельчайшей элемент в множестве, что больше указанного для получение приблизительных (java 5+);
  • HashSet — реализация множества на базе отображения (в действительности на базе HashMap). Без синхронизации;
  • LinkedHashSet — расширение HashSet, элементы упорядочены в порядке добавления, внутренне применяет связной перечень. Без синхронизации;
  • TreeSet — гарантируется логарифмическая зависимость временных затрат на исполнение базисных операций. Интерфейс NavigableSet реализован на базе TreeMap. Без синхронизации. ;
  • EnumSet — специальное множество для объектов типа перечислений. Без синхронизации;

БИЛЕТ №19

Пространства имен в C++

Глобальные переменные видны в произвольных точках программы, начиная с объявления переменной, локальные – лишь в пределах блока. Существуют и статические переменные, заявленные в блока, их область видимости кроме этого ограничивается этим блоком (не путайте с временем судьбы!).

Язык C++ разрешает сократить воздействие имен некоей областью, специально для этого заявленной. Такая область именуется пространством имен и создается посредством главного слова namespace. В пространство имен смогут быть включены переменные, функции.

Создается пространство имен на внешнем уровне:

namespace имя

{

объявления участников пространства

}

К примеру,

namespace smp

{

int count;

void calc();

}

Функции, заявленные в пространстве имен, имеют прямой доступ к вторым участникам пространства. Для определения функции, принадлежащей пространству имен, употребляется оператор разрешения области видимости :: (два двоеточия):

void smp::calc()

{

count++;

}

Доступ к участникам пространства имен извне вероятен двумя методами.

1. При помощи оператора разрешения пространства и явного указания имён области видимости:

smp::calc();

cout

2. При помощи предложения using namespace, включающего данное пространство имен в область видимости текущего блока, что разрешает обращаться к участникам пространства без указания имени пространства:

using namespace smp;

calc();

cout

В случае, если предложение using заявлено на внешнем уровне, видимость участников пространства имен делается глобальной.

При появлении языка C++ элементы, заявленные в библиотеке C++, относились к глобальному пространству имен, не имеющему имени. Действующий стандарт языка C++ все эти элементы относит к пространству имен std.

Требования стандарта соблюдены в компиляторе, входящем в состав Микрософт Visual C++.NET, исходя из этого при разработке программы в данной среде для обращения к потокам cin, cout направляться применять один из вышеприведенных способов:

int a;

std::cout

std::cin a;

std::cout

либо

using namespace std;

int a;

cout

cin a;

cout

Модули

Сам по себе модуль кроме этого есть отдельной областью видимости. Для доступа к глобальным переменным из другого модуля употребляется объявление с атрибутом extern, которое в большинстве случаев размещается в заголовочном файле. Конечно в этом случае, лишь один модуль обязан реально определять это имя.

БИЛЕТ №20

20. Виды конструкторов в С++. Деструкторы в C++.

конструктор по умолчанию — конструктор, не принимающий доводов;

конструктор копирования — конструктор, принимающий в качестве довода объект того же класса (либо ссылку из него);

конструктор преобразования — конструктор, принимающий один довод (эти конструкторы смогут вызываться машинально для преобразования значений других типов в объекты данного класса).

class Complex

{

public:

// Конструктор по умолчанию

// (в этом случае есть кроме этого и конструктором преобразования)

Complex(double i_re = 0, double i_im = 0)

: re(i_re), im(i_im)

{}

// Конструктор копирования

Complex(const Complex направляться)

{

re = obj.re;

im = obj.im;

}

private:

double re, im;

};

[править]

Конструктор по умолчанию

Главная статья: Конструктор по умолчанию

Конструктор не имеющий необходимых доводов. Употребляется при создании массивов объектов, вызываясь для каждого экземпляра. В отсутствие очевидно заданного конструктора по умолчанию его код генерируется компилятором (что на исходном тексте, конечно, не отражается).

[править]

Конструктор копирования

Главная статья: Конструктор копирования

Конструктор, доводом которого есть ссылка на объект того же класса. Используется в C++ для передачи объектов в функции по значению.

Конструктор копирования по большей части нужен, в то время, когда объект имеет указатели на объекты, выделенные в куче. В случае, если программист не создаёт конструктор копирования, то компилятор создаст неявный конструктор копирования, что копирует указатели как имеется, другими словами фактическое копирование данных не происходит и два объекта ссылаются на одинаковые данные в куче. Соответственно попытка трансформации «копии» повредит оригинал, а вызов деструктора для одного из этих объектов при последующем применении другого приведёт к обращению в область памяти, уже не принадлежащую программе.

Довод обязан передаваться конкретно по ссылке, а не по значению. Это вытекает из коллизии: при передаче объекта по значению (в частности, для вызова конструктора) требуется скопировать объект. Но чтобы скопировать объект, нужно позвать конструктор копирования.

[править]

Конструктор преобразования

Конструктор, принимающий один довод. Задаёт преобразование типа собственного довода в тип конструктора. Такое преобразование типа неявно используется лишь если оно уникально.

деструкторы и Конструкторы – особые функции класса, предназначенные для инициализации данных классов.

Конструктор представляет собой особую функцию, которую ваша программа машинально вызывает любой раз при создании объекта. Конструктор имеет такое же имя, как и класс объекта.Конструктор не имеет возвращаемого значения, но вы не показываете ему тип void. Вместо этого вы просто не показываете возвращаемое значение по большому счету.В то время, когда ваша программа формирует объект, она может передать параметры конструктору на протяжении объявления объекта.C++ разрешает вам перегружать конструкторы и разрешает применять значения по умолчанию для параметров.Деструктор представляет собой особую функцию, которую ваша программа вызывает машинально любой раз при уничтожении объекта. Деструктор имеет такое же имя, как и класс объекта, но его имя предваряется знаком тильды (~).Конструкторы не смогут быть virtual и static. Деструктор возможно virtual, но не может быть static.

Class stack {

Chart *

Int m;

Int top;

Public:

Stack(int);

Stack();

Stack(chart*, int);

~stack();

}

Stack::stack()

{s=new char[512]

m=512;

top =0}

БИЛЕТ №21

Перегрузка функций – один из главных качеств языка C++. Она снабжает статический полиморфизм, и комфорт и гибкость. Значительно чаще перегрузке подвергаются конструкторы. Одной из самые важных форм перегрузки конструкторов есть конструктор копирования. Возможность задавать доводы по умолчанию применяют в качестве альтернативы перегрузке функций.

Перегрузка функций – это применение одного имени для нескольких функций. Секрет перегрузки содержится в том, что каждое переопределение функции должно

применять или другие типы параметров, или второе их количество. Лишь эти различия разрешают компилятору выяснить, какую функцию направляться позвать в том либо другом случае.

#include

using namespace std;

int myfunc (int i);

double myfunc (double i);

int main ()

{

count

count

return 0;

}

double myfunc (double i);

{

return i;

}

int myfunc (int i)

{

return i;

}

В следующей программе перегруженные варианты функции myfunc () применяют различное количество параметров.

#include

using namespace std;

int myfunc (int i);

int myfunc (int i, int j);

int main ()

{

count

count

return 0;

}

Int myfunc (int i)

{

return i;

}

Int myfunc(int i, int j)

{

return i*j;

}

направляться не забывать, что перегруженные функции должны различаться типами либо числом параметров. Тип возвращаемого значения не разрешает перегружать функции. К примеру, следующий вариант перегрузки функции myfunc() неверен.

Int myfunc(int i);

func (int i);

Время от времени объявления двух функций снаружи отличаются, но практически совпадают. Рассмотрим следующие объявления.

void f(int *p);

void f (int p[]);

направляться не забывать, что компилятор не различает выражения *p и p[]. Следовательно, не смотря на то, что снаружи два прототипа функции f различаются, в действительности они абсолютно совпадают.

С перегрузкой функций тесно связан механизм перегрузки операторов. В языке C++ возможно перегрузить большая часть операторов, настроив их на конкретный класс. Перегруженный оператор сохраняет собственное начальное назначение. Легко комплект типов, к каким его возможно применить, расширяется.

Перегрузка операторов осуществляется посредством операторных функций, каковые определяют действия перегруженных операторов применительно к соответствующему классу. Операторные функции создаются посредством главного слова operator.Операторные функции смогут быть как участниками класса, так и простыми функциями. Но простые операторные функции, в большинстве случаев, объявляют дружественными по отношению к классу, для которого они перегружают оператор. В каждом из этих случаев операторная функция объявляется по-различному.

Операторная функция-член имеет следующий вид:

тип_возвращаемого_значения имя_класса : : operator # (список_аргументов)

{

………// Операции

}

В большинстве случаев операторная функция возвращает объект класса, с которым она трудится, но тип возвращаемого значения возможно любым. Знак # заменяется перегружаемым оператором. При перегрузке унарного оператора список_аргументов остаётся безлюдным. При перегрузке двоичного оператора перечень список_аргументов содержит один параметр.

Эта программа создаёт класс loc,в котором храняться географические координаты. В ней перегружается оператор «+».

#include

using namespacestd;

class loc {

int longitude, latitude;

public:

loc () {}

loc (int lg, int lt){

longitude=lg;

latitude=

}

void show() {

count

count

}

Loc operator+(loc какое количество2);

};

loc loc : : operator+(loc op2)

{

loc temp;

temp.longitude=ob2.longitude + longitude;

temp.latitude=op2.latitude + latitude;

return temp;

}

int main()

{

loc ob1 (10,20), ob2 (5,30);

ob1.show();//Выводит на экран числа 10 20

ob2.show();//Выводит на экран числа 5 30

ob1=ob1+ob2;

ob1.show();//Выводит на экран числа 15 50

return 0;

}

Как видим, функция operator+() имеет лишь один параметр, не обращая внимания на то, что она перегружает двоичный оператор.

Обстоятельство содержится в том, что операнд, стоящий в левой части оператора, передаётся операторной функции неявно посредством указателя this.Из этого следует ответственный вывод: при перегрузке двоичного оператора вызов операторной функции генерируется объектом, стоящим в левой части оператора.

Помимо этого, потому, что операторная функция operator+()возвращает объект типа loc, допускается следующее выражение:

(ob1+ob2).show();

В данной ситуации операторная функция создаёт временный объект, что уничтожается по окончании возвращения из функции show().

направляться не забывать, что операторная функция может возвращать объекты любых типов, и что эти типы зависят лишь от конкретного приложения. Но, в большинстве случаев, операторные функции возвращают объекты класса, с которым они трудятся.

Неспециализированная форма префиксной и постфиксной операторных функций:

//префиксный оператор

тип operator#(){

//тело префиксного оператора

}

//Постфиксный оператор

тип operator#(int i){

//тело постфиксного оператора

}

Сокращённые операторы присваивания кроме этого возможно перегружать.

loc loc : : operator+=(loc op2)

{

longitude=op2.longitude + longitude;

latitude=ob2.latitude + latitude;

return *this;

}

Запрещено перегружать операторы: «.», «: :», «.*», «?».

Операторы возможно перегружать посредством дружественных функций, не являющихся участниками класса. Это значит, что дружественные функции не приобретают неявного указателя this. Следовательно, перегруженная операторная функция приобретает параметры очевидно. Так, при перегрузке двоичного оператора дружественная функция приобретает два параметра, а при перегрузке унарного оператора – один. Первым параметром дружественной функции, перегружающий двоичный оператор, есть его левый операнд, а вторым – правый операнд.

БИЛЕТ №22

Шаблоны C++

Шабло?ны— средство языка C++, предназначенное для кодирования обобщённых методов, без привязки к некоторым параметрам (к примеру, типам данных, размерам буферов, значениям по умолчанию).

В C++ допустимо создание шаблонов функций и классов.

Шаблоны разрешают создавать параметризованные функции и классы. Параметром возможно любой тип либо значение одного из допустимых типов (целое число, enum, указатель на любой объект с глобально дешёвым именем). К примеру, нам нужен какой-то класс:

class SomeClass{

int SomeValue;

int SomeArray[20];

}

Для одной конкретной цели мы можем применять данный класс. Но, внезапно, цель мало изменилась, и нужен еще один класс. Сейчас необходимо 30 элементов массива SomeArray и вещественный тип SomeValue и элементов SomeArray. Тогда мы можем отвлечься от конкретных типов и применять шаблоны с параметрами. Синтаксис: в начале перед объявлением класса напишем слово template и укажем параметры в угловых скобках. В отечественном примере:

template class SomeClass{

SomeValueType SomeValue;

SomeValueType SomeArray[ ArrayLength ];

}

Тогда для первой модели пишем:

SomeClass SomeVariable;

для второй:

SomeClass SomeVariable2;

Не смотря на то, что шаблоны предоставляют краткую форму записи участка кода, в действительности их применение не уменьшает исполнимый код, поскольку для каждого комплекта параметров компилятор создаёт отдельный экземпляр функции либо класса.

Синтаксис описания шаблона

Шаблон функции начинается с главного слова template, за которым в угловых скобках направляться перечень параметров. После этого направляться объявление функции:

template

void sort( T array[], int size ); // прототип: шаблон sort заявлен, но не выяснен

template

void sort( T array[], int size ) // определение и объявление

{

T t;

for (int i = 0; i size — 1; i++)

for (int j = size — 1; j i; j—)

if (array[j] array[j-1])

{

t = array[j];

array[j] = array[j-1];

array[j-1] = t;

}

}

template // целочисленный параметр

char* read()

{

char *Buffer = new char[ BufferSize ];

/* считывание данных */

return Buffer;

}

Главное слово typename показалось недавно, исходя из этого стандарт[1] допускает применение class вместо typename:

template

Вместо T допустим каждый идентификатор.

[править]Пример применения

Несложным примером помогает определение минимума из двух размеров.

В случае, если a меньше b то вернуть а, в противном случае — вернуть b

В отсутствие шаблонов программисту приходится писать отдельные функции для каждого применяемого типа данных. Не смотря на то, что многие языки программирования определяют встроенную функцию минимума для элементарных типов (таких как вещественные числа и целые), такая функция может пригодиться и для сложных (к примеру «время» либо «строчок») и сверхсложных («игрок» в онлайн-игре) объектов.

Так выглядит шаблон функции определения минимума:

template

T min( T a, T b )

{

return a b ? a : b;

}

Для вызова данной функции возможно её имя:

min( 1, 2 );

min( ‘a’, ‘b’ );

min( string( abc ), string( cde ) );

Вызов шаблонной функции

По большому счету говоря, для вызова шаблонной функции, нужно указать значения для всех параметров шаблона. Для этого по окончании имени шаблона указывается перечень значений в угловых скобках:

int i[5] = { 5, 4, 3, 2, 1 };

sort( i, 5 );

char c[] = бвгда;

sort( c, strlen( c ) );

sort( c, 5 ); // неточность: у sort параметр int[] а не char[]

char *ReadString = read();

delete [] ReadString;

ReadString = read();

Для каждого комплекта параметров компилятор генерирует новый экземпляр функции. Процесс создания нового экземпляра именуется инстанцированием шаблона.

В примере выше компилятор создал две специализации шаблона функции sort (для типов char и int) и две специализации шаблона read (для значений BufferSize 20 и 30). Последнее вероятнее расточительно, поскольку для каждого вероятного значения параметра компилятор будет создавать новые и новые экземпляры функций, каковые будут различаться только одной константой.

Выведение значений параметров

В некоторых случаях компилятор может сам вывести (логически выяснить) значение параметра шаблона функции из довода функции. К примеру, при вызове вышеописанной функции sort необязательно показывать параметр шаблона (если он сходится с типом элементов довода-массива):

int i[5] = { 5, 4, 3, 2, 1 };

sort( i, i + 5 ); // вызывается sort

char c[] = бвгда;

sort( c, c + strlen( c ) ); // вызывается sort

Допустимо выведение и в более сложных случаях.

При применения шаблонов классов с целыми параметрами кроме этого допустимо выведение этих параметров. К примеру:

template

class IntegerArray

{

int Array[ size ];

/* … */

};

template // Прототип шаблона

void PrintArray( IntegerArray array ) { /* … */ } // Вызов шаблона

// Применение объекта шаблона

IntegerArray ia;

PrintArray( ia );

Правила выведения введены в язык для облегчения применения шаблона и для избежания вероятных неточностей, к примеру попытка применения sort для сортировки массива знаков.

В случае, если параметр шаблона возможно вывести по нескольким доводам, то итог выведения должен быть в точности однообразен для всех этих доводов. К примеру, следующие вызовы ошибочны:

min (0, ‘a’);

min (7, 7.0);

[править]Ошибки в шаблонах

Кое-какие неточности в описании шаблона смогут быть распознаны уже в месте описания. Эти неточности не зависят от конкретных параметров. К примеру:

template

void f( T data )

{

T *pt = 7; // неточность: инициализация указателя целым числом

datA = 0; // неточность: малоизвестный идентификатор datA

*pt = data // неточность: нет точки с запятой

}

Неточности, которые связаны с применением конкретных параметров шаблона, нельзя выявить перед тем, как шаблон использован. К примеру, шаблон min сам по себе не содержит неточностей, но применение его с типами, для которых операция ‘

struct A

{

int a;

};

A obj1, obj2;

min( obj1, obj2 );

В случае, если ввести операцию ‘

friend inline bool operator ( const A a1, const A a2 ) { return a1.a a2.a; }

min( obj1, obj2 );

Шаблоны классов

В классе, реализующем связный перечень целых чисел, методы добавления нового элемента перечня, поиска нужного элемента не зависят от того, что элементы перечня — целые числа. Те же методы использовались бы и для перечня знаков, строчков, дат, классов игроков, и без того потом.

template

class List

{

/* … */

public:

void Add( const T Element );

bool Find( const T Element );

/* … */

};

[править]Использование шаблонов

Для применения шаблона класса, нужно указать его параметры:

List li;

List ls;

направляться.Add( 17 );

ls.Add( Hello! );

Технические детали

Параметры шаблонов

Параметрами шаблонов смогут быть: параметры-типы, параметры простых типов, параметры-шаблоны.

Для параметров любого типа возможно показывать значения по умолчанию.

template class T1, // параметр-тип

typename T2, // параметр-тип

int I, // параметр простого типа

T1 DefaultValue, // параметр простого типа

template class T3, // параметр-шаблон

class Character = char // параметр по умолчанию

[править]Параметры-шаблоны

В случае, если в шаблоне класса либо функции нужно применять одинаковый шаблон, но с различными параметрами, то употребляются параметры-шаблоны. К примеру:

template class Type, template class Container

class CrossReferences

{

Container mems;

Container refs;

/* … */

};

CrossReferences cr1;

CrossReferences cr2;

БИЛЕТ №23

Дабы комфортно трудиться с исключениями в С++ вам необходимо знать только три главных слова:

  • try (пробовать) — начало блока исключений;
  • catch (поймать) — начало блока, ловящего исключение;
  • throw (кинуть) — главное слово, создающее (возбуждающее) исключение.

А сейчас пример, демонстрирующий, как применить то, что вы определили:

void func(){ try { throw 1; } catch(int a) { cout В случае, если выполнить данный фрагмент кода, то мы возьмём следующий итог:
Caught exception number: 1

Сейчас закоментируйте строчок throw 1; и функция выдаст таковой итог:

No exception detected!

Как видите все весьма легко, но в случае, если это применить с умом, таковой подход покажется вам весьма замечательным средством обработки неточностей. Catch может ловить любой тип данных, так же как и throw может кинуть эти любого типа. Т.е. throw AnyClass(); будет верно трудиться, так же как и catch (AnyClass d) {};.

Как уже было сообщено, catch может ловить эти любого типа, но вовсе не обязательно при это показывать переменную. Т.е. замечательно будет трудиться что-нибудь типа этого:

catch(dumbclass) { }

равно как и

catch(dumbclass) { }

Так же возможно поймать и все исключения:

catch(…) { }

Троеточие в этом случае говорит о том, что будут пойманы все исключения. При таком подходе нельзя указать имя переменной. , если кидаются эти нестандартного типа (экземпляры определенных вами классов, структур и т.д.), лучше ловить их по ссылке, в противном случае вся кидаемая переменная будет скопирована в стек вместо того, дабы указатель на нее. В случае, если кидаются эти нескольких типов и вы желаете поймать конкретную переменную (вернее, переменную конкретного типа), то возможно применять пара блоков catch, ловящих собственный тип данных:

try { throw 1;// throw ‘a’;}catch (long b) { cout Создание исключений

В то время, когда возбуждается необыкновенная обстановка, программа просматривает стек функций до тех пор, пока не находит соответствующий catch. В случае, если оператор catch не отыскан, STL будет обрабатывать исключение в стандартном обработчике, что делает все менее изящно, чем имели возможность бы сделать вы, показывая какие-то непонятные (для конечного пользователя) сообщения и в большинстве случаев неудачно завершая программу.

Но более серьёзным моментом есть то, что до тех пор пока просматривается стек функций, вызываются деструкторы всех локальных классов, так что вам не требуется забодиться об освобождении памяти и т.п.

Перегрузка глобальных операторов new/delete

А на данный момент хотелось бы послать вас к статье Как найти утечку памяти. В ней рассказывается, как найти неправильное управление распределением памяти в вашей программе. Вы имеете возможность задать вопрос, при чем тут перегрузка операторов? В случае, если перегрузить стандартные new и delete, то раскрываются много возможностей по отслеживанию неточностей (причем неточностей довольно часто критических) посредством исключений. К примеру:

char *a;try{ a = new char[10];}catch (…){ // a не создан — обработать неточность распределения памяти, // выйти из программы и т.п.}// a удачно создан, продолжаем исполнение

Это, на первый взгляд, думается дольше, чем стандартная проверка в С а равен NULL?, но в случае, если в программе выделяется дюжина динамических переменных, то таковой способ оправдывает себя.

КАК ЛЕГКО И БЫСТРО МОНТИРОВАТЬ ВИДЕО В WONDERSHARE FILMORA?! + Ссылки на скачивание | Туториал


Интересные записи:

Понравилась статья? Поделиться с друзьями: