Рассмотрим очень простой класс строк string:
struct string {
char* p;
int size; // размер вектора, на который указывает p
string(int sz) { p = new char[size=sz]; }
~string() { delete p; }
};
Строка - это структура данных, состоящая из вектора символов и длины этого вектора. Вектор создается конструктором и уничтожается деструктором. Однако это может привести к неприятностям.
Например:
void f()
{
string s1(10);
string s2(20);
s1 = s2;
}
будет размещать два вектора символов, а присваивание s1=s2 будет портить указатель на один из них и дублировать другой. На выходе из f() для s1 и s2 будет вызываться деструктор и уничтожать один и тот же вектор с непредсказуемо разрушительными последствиями. Решение этой проблемы состоит в том, чтобы соответствующим образом определить присваивание объектов типа string:
struct string {
char* p;
int size; // размер вектора, на который указывает p
string(int sz) { p = new char[size=sz]; }
~string() { delete p; }
void operator=(string&)
};
void string::operator=(string& a)
{
if (this == &a) return; // остерегаться s=s;
delete p;
p=new char[size=a.size];
strcpy(p,a.p);
}
Это определение string гарантирует, и что предыдущий пример будет работать как предполагалось. Однако небольшое изменение f() приведет к появлению той же проблемы в новом облике:
void f()
{
string s1(10);
s2 = s1;
}
Теперь создается только одна строка, а уничтожается две. К неинициализированному объекту определенная пользователем операция присваивания не применяется. Беглый взгляд на string::operator=() объясняет, почему было неразумно так делать: указатель p будет содержать неопределенное и совершенно случайное значение. Часто операция присваивания полагается на то, что ее аргументы инициализированы. Для такой инициализации, как здесь, это не так по определению. Следовательно, нужно определить похожую, но другую, функцию, чтобы обрабатывать инициализацию:
struct string {
char* p;
int size; // размер вектора, на который указывает p
string(int sz) { p = new char[size=sz]; }
~string() { delete p; }
void operator=(string&)
string(string&);
};
void string::string(string& a)
{
p=new char[size=a.size];
strcpy(p,a.p);
}
Для типа X инициализацию тем же типом X обрабатывает конструктор X(X&). Нельзя не подчеркнуть еще раз, что присваивание и инициализация - разные действия. Это особенно существенно при описании деструктора. Если класс X имеет конструктор, выполняющий нетривиальную работу вроде освобождения памяти, то скорее всего потребуется полный комплект функций, чтобы полностью избежать побитового копирования объектов:
class X {
// ...
X(something); // конструктор: создает объект
X(&X); // конструктор: копирует в инициализации
operator=(X&); // присваивание: чистит и копирует
~X(); // деструктор: чистит
};
Есть еще два случая, когда объект копируется: как параметр функции и как возвращаемое значение. Когда передается параметр, инициализируется неинициализированная до этого переменная - формальный параметр. Семантика идентична семантике инициализации. То же самое происходит при возврате из функции, хотя это менее очевидно. В обоих случаях будет применен X(X&), если он определен:
string g(string arg)
{
return arg;
}
main()
{
string s = "asdf";
s = g(s);
}
Ясно, что после вызова g() значение s обязано быть "asdf". Копирование значения s в параметр arg сложности не представляет: для этого надо взывать string(string&). Для взятия копии этого значения из g() требуется еще один вызов string(string&); на этот раз инициализируемой является временная переменная, которая затем присваивается s. Такие переменные, естественно, уничтожаются как положено с помощью string::~string() при первой возможности.
Другие работы по теме:
Метод решения уравнений Ньютона - Рафсона
Метод Ньютона-Рафсона, также известный как Метод Ньютона, представляет собой обобщенный метод поиска корня уравнения Примем x = xj в качестве j-го приближения к корню уравнения (1). Предположим, что xj не является решением. Следовательно,
Подсчет и индикация деталей
З А Д А Н И Е № 13 на курсовую работу по дисциплине "Основы микропроцессорной техники" Разработать принципиальную схему и программу функционирования микропроцессорной системы, выполненной на базе однокристального микроконтроллера серии МК51, осуществляющего подсчет и индикацию количества деталей разного размера на конвейере.
KURS
Задание. Создать МП систему управления настройкой приемника. Упрощенная схема приемника изображена на рис. 1. Рис 1 Контур приемника состоит из индуктивности L
Транзисторний перетворювач з дроселем в первинному ланцюзі
Транзисторний перетворювач із дроселем у первинному ланцюзі на основі найпростішої схеми, із системою керування. Розробка основної структурної схеми, принципової схеми, силової частини, системи керування, силової частини і вузлів системи керування.
Выражения и Операторы
Выражения. Операторы Выражения. Пустой оператор. Блоки. Операторы if. Операторы switch. Оператор while. Оператор for. Описания.
Динамические структуры данных
Средства создания динамических структур данных. Формат описания ссылочного типа. Структура памяти во время выполнения программы. Линейные списки, стек, очередь. Организация списков в динамической памяти. Пример создания списка в обратном порядке.
Кластеризация с помощью нейронных сетей
Сущность, структура, алгоритм функционирования самообучающихся карт. Начальная инициализация и обучение карты. Сущность и задачи кластеризации. Создание нейронной сети со слоем Кохонена при помощи встроенной в среды Matlab. Отличия сети Кохонена от SOM.
Класс Строка
Вот довольно реалистичный пример класса string. В нем производится учет ссылок на строку с целью минимизировать копирование и в качестве констант применяются стандартные символьные строки C++.
Свободная Память
Если вы пользовались классом slist, вы могли обнаружить, что ваша программа тратит на заметное время на размещение и освобождение объектов класса slink.
Консольное приложение на Дельфи
Хоть и консольные приложения уже давно вышли из моды, с помощью них можно легко делать рутинные операции. Они занимают не так много места, не требовательны к ресурсам и быстро выполняются.
Интегрирование методом Симпсона
Московский Авиационный Институт Расчетно графическая работа по: алгоритмическим языкам и программированию. кафедра 403 Выполнил: Гуренков Дмитрий гр. 04-109 /____________/
Вычисление вероятности игры в КРЭКС(кости)
Игра в “крэкс”( 2 кости Правила такие.Игрок бросает 2 кости и подсчитывает сумму S выпавших очков. Он сразу же выигрывает,если S=7 или 11,и проигрывает,если S есть 2;3 или 12. Всякая другая сумма – это его “пойнт”.Если в первый раз выпадает “пойнт”,то игрок бросает кости до тех пор,пока он или не выйграет,выбросив свой “пойнт”, или не проиграет,получив сумму очков,равную 7.Какова вероятность выигрыша?
Turbo Basic прикладной
Министерство общего и профессионального образования Российской федерации Южно-Уральский Государственный университет Кафедра строительных материалов
Программирование микроконтроллера
Разработка алгоритма работы устройства, описание выбора элементной базы и работы принципиальной схемы. Текст программы, инициализация указателя стека, структура системы и ресурсов микроконтроллера. Запись кодов при программировании данного устройства.
Средства машинной коммуникации персонального компьютера
Микросхема универсального асинхронного приемо-передатчика. Функции и адресация регистров, их виды. Определение состояния модема. Примеры простейших коммуникационных программ. Инициализация и передача данных. Глобальные компьютерные сети, их компоненты.
Примеры решения задач по программированию
Написание программы вычисления сопротивления электрической цепи, состоящей из двух параллельно и двух последовательно соединенных сопротивлений. Схема машинного алгоритма по условию задачи. Применение операций при написании программ на языке C/C++.
Turbo Basic прикладной
Министерство общего и профессионального образования Российской федерации Южно-Уральский Государственный университет Кафедра строительных материалов
Одномерные и двумерные массивы
Кафедра: Автоматика и информационные технологии ОДНОМЕРНЫЕ И ДВУМЕРНЫЕ МАССИВЫ Содержание 1. Теоретическая часть 1.1 Определение массива 1.2 Расположение в памяти
Манипулирование с целыми числами произвольной длины
Манипулировани с целыми числами произвольной длины Постановка задачи: Составить набор процедур манипулирования с целыми числами произвольной длины. Процедуры должны обеспечивать: формирование и ввод целых чисел произвольной длины, сложение, вычитание, сравнение и умножение целых чисел. Работоспособность процедур продемонстрировать на демонстрационной программе.
Вычисление вероятности игры в КРЭКСкости
Игра в “крэкс”( 2 кости Правила такие.Игрок бросает 2 кости и подсчитывает сумму S выпавших очков. Он сразу же выигрывает,если S=7 или 11,и проигрывает,если S есть 2;3 или 12. Всякая другая сумма – это его “пойнт”.Если в первый раз выпадает “пойнт”,то игрок бросает кости до тех пор,пока он или не выйграет,выбросив свой “пойнт”, или не проиграет,получив сумму очков,равную 7.Какова вероятность выигрыша?
Символьные массивы
Введение Массив - это упорядоченная совокупность однотипных данных. Каждому элементу массива соответствует один или несколько индексов, определяющих положение элемента в массиве. Индексы образуют упорядоченные последовательности.
Интерпретатор 2
Федеральное агентство по образованию ОМСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ Кафедра информатики и вычислительной техники Пояснительная записка
Программа Умножение многочленов
Содержание Введение 1. Анализ предметной области 2. Постановка задачи 3. Техническая часть 3.1 Разработка схемы алгоритма 3.2 Реализация программы на языке программирования
Массивы и указатели
0.doc 15 / 15 Массивы и указатели Массивы Инициализация массивов и классы памяти Указатели массивов Функции, массивы и указатели Использование указателей при работе с массивами
Массивы и указатели в языке программирования Си
Лабораторная работа "Массивы и указатели в языке программирования Си++" Теоретические сведения Цель работы: ознакомиться с основными принципами работы с одномерными и двумерными массивами. Освоить работу с указателями и операциями над указателями.
Классы: копирование и присваивание
Конструктор копий служит для создания новых объектов из существующих. Операция присваивания нужна для того, чтобы сделать один существующий объект эквивалентным другому существующему.