Перейти к содержимому

Swap c что это

  • автор:

Функция SWAP в языке С: что это и как работает

Lorem ipsum dolor

Функция SWAP в С — простой способ обменять значения двух переменных, которые содержат одинаковые типы данных. Эта функция доступна из стандартной библиотеки. В основном ее применяют для работы с небольшими данными, потому что она несет в себе конструкцию из копирования значений переменных и обмена этих значений. Такая конструкция задействует определенный объем памяти. А это значит, что , если применить функцию SWAP в Си для работы с большими данными, с низится производительность программы.

Функция SWAP в С

Для простой реализации функции SWAP в Си из стандартной библиотеки можно воспользоваться следующим шаблоном:

#include

using std::swap;

int main()

int x = 8;

int y = 9;

// после выполнения программы результат будет таким: x = 9, y = 8

>

Функция SWAP в С может применяться и в более сложных конструкциях, например:

#include

#include

#include

int main ()

int a=100, b=200; //присваиваем значения переменным: a=100, b=200

std::swap(a,b); // функция swap меняет значения переменных: a=200, b=100

std::vector foo (2,a), bar (3,b) //проводим операции: foo:2×200 bar:3×100

std::swap(foo, bar); //swap меняет значения операций: foo:3×100 bar:2×200

std:: cout < < “ foo содержит: “;

for (std::vector::iterator it=foo.begin(); it!=foo.end(); ++it)

std::cout < < ` < < *it;

std::cout < < `\n`;

return 0;

>

После выполнени я э та программ а нам выдаст следующий результат:

foo содержит: 100 100 100

Функция SWAP в С работает не только с числами, но и с другими типами данных, например со строками:

#include

using namespace std;

int main()

string a = “Функция“;

string b = “Программирование“;

cout

cout

swap (a, b);

cout < < “Значение переменной «а» после применения функции SWAP: “

cout

retorn 0;

>

Результат выполнения такой программы будет следующий:

Значение переменной «а» до применения функции SWAP: Функция

Значение переменной «b» до применения функции SWAP: Программирование

Значение переменной «а» после применения функции SWAP: Программирование

Значение переменной «b» после применения функции SWAP: Функция

Заключение

Функция SWAP в С работает с любыми типами данных. Чтобы она сработала, у переменных обязательно должно быть какое-то значение. Она ничего не возвращает, а просто меняет местами значения переменных.

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

собственная функция swap, почему и как она работает?

Функция свапает значения, было 10 и 20, стало 20 и 10. Функция должна принимать два указателя на тип int, а в итоге принимает две переменные типа int, и еще, непонятно почему, работающее тело функции «a = b; b = a», не понимаю, как это работает?

Отслеживать
задан 18 июн 2018 в 17:07
31 1 1 золотой знак 1 1 серебряный знак 2 2 бронзовых знака

Для начала уберите using namespace std; и убедитесь, что ваша функция на самом деле не используется. Также см. ADL

18 июн 2018 в 17:16
Ваша функция никак не работает. Как правильно заметил VTT, она вообще не используется в вашем коде.
18 июн 2018 в 18:03

Можно не убирать using. , а добавить :: перед swap . Этого будет достаточно, чтоб убедиться в некомпилируемости такого вызова nfrjq функции 🙂

Swap c что это

Когда нужно изменить состояние одного или нескольких объектов, и на любом этапе модификации может возникнуть ошибка, для создания кода, устойчиваого к ошибкам, может применяться идиома копирования и замены ( copy-and-swap idiom ). Суть данной идиомы состоит в следующей последовательности действий:

  1. Создаем копию объекта(ов)
  2. Изменяем копию. При этом оригинальные объекты остаются нетронутыми
  3. Если все изменения прошли успешно, заменяем оригинальный объект измененной копией. Если же при изменении копии на каком-то этапе возникла ошибка, то оригинальный объект не заменяется.

Обычно эта идиома применяется в функциях и частным, хотя и распространенным, случаем ее применения является оператор присваивания. В общем случаем это выглядит так:

// оператор присвоения некоторого класса Copyable Copyable& operator=(const Copyable& obj) < Copyable copy; // создаем копию через конструктор копирования swap(copy); // обмениваем значения копии и оригинального объекта return *this; > // некоторая функция для обмена значениями void swap(Copyable& copy) noexcept;

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

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

Устойчивость к исключениям заключается в том, что в операторе присваивания нет точки, где генерация исключения могла бы привести к утечке памяти. Приведённая выше реализация также устойчива к присваиваниям объекта самому себе (a=a), однако содержит издержки, связанные с тем, что временная копия в этом случае тоже будет создаваться. Исключить издержки можно дополнительной проверкой:

// оператор присвоения некоторого класса Copyable Copyable& operator=(const Copyable& obj) < Copyable copy; // создаем копию через конструктор копирования if(this != &obj) // если не текущий объект swap(copy); // обмениваем значения копии и оригинального объекта return *this; > // некоторая функция для обмена значениями void swap(Copyable& copy) noexcept;

Рассмотрим реализацию этого принципа. Но сначала посмотрим, какую проблему мы можем решить с помощью подобной идиомы. Пусть у нас есть следуюший класс:

template class Array < public: Array(unsigned size) : data< new T[size] >, size <> // выделяем память ~Array() < delete[] data;>// освобождаем память // оператор присвоения Array& operator=(const Array& array) < if (&array != this) < delete[] data; // освобождаем память size = array.size; data = new T[size]; // выделяем память - может столкнуться с std::bad_alloc // копируем значения for (unsigned i<>; i < size; ++i) data[i] = array.data[i]; // можем столкнуться с исключением в зависимости от типа T >return *this; > // оператор индексирования для доступа к элементам T& operator[](unsigned index) < return data[index]; >unsigned getSize() const private: T* data; // хранимые данные unsigned size; // размер массива >;

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

Array(unsigned size) : data< new T[size] >, size <> // выделяем память ~Array() < delete[] data;>// освобождаем память

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

data = new T[size];

Но надо отметить, что оператор new[] генерирует исключение std::bad_alloc , если по какой-то причине не удалось выделить память. Например, когда надо выделить память под очень большой массив, который не помещается в доступной памяти.

Если оператор new[] не может выделить новую память, указатель data становится так называемым висячим указателем — указателем на освобожденную память. Поэтому даже если мы обработаем исключение bad_alloc, то объект Array будет непригоден для использования. А на этапе вызове деструктора мы столкнемся со сбоем.

Далее в цикле присваиваем значения элементам массива data:

data[i] = array.data[i];

В данном случае элементу типа T присваивается значение типа T. Однако T может представлять любой тип. И этот тип должен поддерживать оператор присвоения. Но в этом операторе присвоения также может быть реализована какая-нибудь логика, которая может генерировать исключения.

Изменим код, применив идиому копирования и замены:

#include template class Array < public: Array(unsigned size) : data< new T[size] >, size <> // выделяем память ~Array() < delete[] data;>// освобождаем память Array(const Array& array) : Array < for (unsigned i <>; i < size; ++i) data[i] = array.data[i]; >// оператор присвоения Array& operator=(const Array& other) < Arraycopy< other >; // вызываем конструктор копирования swap(copy); // обмениваем значениями return *this; > // оператор индексирования для доступа к элементам T& operator[](unsigned index) < return data[index]; >// функция обмена значениями void swap(Array& other) noexcept < std::swap(data, other.data); // обмениваем два указателя std::swap(size, other.size); // обмениваем размеры >unsigned getSize() const private: T* data; // хранимые данные unsigned size; // размер массива >; int main() < const unsigned count ; // количество элементов Array values; // создаем объект // присваиваем элементам values некоторые значения for (unsigned i <>; i < count; ++i) < values[i] = i; >Array numbers; numbers = values; // применение оператора присвоения // выводим элементы из объекта numbers на консоль for (unsigned i <>; i < numbers.getSize(); ++i) < std::cout std::cout

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

Array(const Array& array) : Array < for (unsigned i <>; i

Таким образом, мы получим копию текущего объекта.

Для обмена значениями реализована функция swap:

void swap(Array& other) noexcept < std::swap(data, other.data); // обмениваем два указателя std::swap(size, other.size); // обмениваем размеры >

Для упрощения для обмена значениями применяется стандартная функция std::swap из стандартной библиотеки C++, которая обменивает значения двух параметров, используя их оператор копирования. Фактически здесь обмениваем значениями по отдельности элементы динамического массива и размеры массива.

В функции оператора присваивания применяем конструктор копирования и функцию swap:

Array& operator=(const Array& other) < Arraycopy< other >; // вызываем конструктор копирования swap(copy); // обмениваем значениями return *this; >

Далее в функции main мы можем создать объект Array и присвоить его другому объекту:

Array numbers; numbers = values; // применение оператора присвоения
0 1 2 3 4

Хотя часто подобный способ применяется именно в операторах присвоения, но также он может применяться в других ситуациях, где необходимо выполнить устойчивую к исключениям модификацию объекта. И всегда принцип будет тот же. Сначала копируем объект, который надо изменить. Далее выполняем над объектом-копией изменения. И если все пройдет удачно, обмениваем значениями целевой объект и объект-копию.

Функция swap (auto_handle)

Переключает объекты между одним auto_handle и другим.

Синтаксис

template void swap( auto_handle % _left, auto_handle % _right ); 
Параметры

_Левой
Объект auto_handle .

_Правильно
Другой auto_handle .

Пример

// msl_swap_auto_handle.cpp // compile with: /clr #include using namespace System; using namespace msclr; int main() < auto_handles1 = "string one"; auto_handle s2 = "string two"; Console::WriteLine( "s1 = '', s2 = ''", s1->ToString(), s2->ToString() ); swap( s1, s2 ); Console::WriteLine( "s1 = '', s2 = ''", s1->ToString(), s2->ToString() ); > 
s1 = 'string one', s2 = 'string two' s1 = 'string two', s2 = 'string one' 

Требования

Файл

Msclr пространства имен

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *