Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД_ответы_catsto_NEW.doc
Скачиваний:
17
Добавлен:
16.04.2019
Размер:
365.57 Кб
Скачать

Int m_nCount;

friend class CStr;

_str () {

m_pszData = 0; m_nCount = 1;

}

_str (const char *p)

{

m_nCount = 1;

m_pszData = new char [strlen(p) + 1];

strcpy (m_pszData, p);

}

~_str () { delete []m_pszData;}

void AddRef() {m_nCount++;}

void Release () {m_nCount--; if(m_nCount==0) delete this;}

};

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

Но вот новая строка friend class CStr. Это означает, что класс _str объявил своим другом класс CStr, а другу позволено обращаться к закрытым членам класса.

Обратим внимание, что в конструкторах счетчик ссылок делается равным 1, т.е. считается, что создатель объекта обязан его использовать.

Метод AddRef тривиален, а вот Release – уменьшает количество ссылок и если ссылок больше нет, то вызывает деструктор. Деструктор применяется к указателю this. Это зарезервированное слово. This – это указатель на объект, для которого вызван метод.

При рассмотрении реализации CStr убеждаемся, что теперь основная задача конструкторов создать объект управления данными, а деструктор просто освобождает этот объект (уменьшает число пользователей данных). Для будущих нужд мы определили метод len, который вычисляет длину строки.

class CStr {

_str* m_pStr;

public:

CStr () {m_pStr = new _str;}

CStr (const char * p) {m_pStr = new _str(p);}

~ CStr () { m_pStr -> Release();}

int len() const {return (m_pStr->m_pszData)? strlen(m_pStr->m_pszData): 0; }

};

Собственно конструктор копии:

CStr (const CStr &s)

{ m_pStr = s. m_pStr;

m_pStr->AddRef(); }

Вот ради этого все и делалось! Обратите внимание, никакого копирования данных нет. Просто запоминается указатель и увеличивается число ссылок.

Другое применение объектов с подсчетом ссылок:

Одно из применений подсчета ссылок – быстрое копирование. Этим применение не исчерпывается. Подсчет ссылок применяется и в тех случаях, когда реальный ресурс не может быть скопирован, но должен быть освобожден, когда его никто не использует. Такой случай встречается, например, в COM-технологии, которая определяет правила создания и использования ActiveX.

  1. Средства обработки текстовых данных. Форматирование строк в C++ и C#. Эффективность формирования строк и класс StringBuilder в C#.

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

Форматирование строк в C#:

http://www.realcoding.net/article/view/4270

Пример с Format:

displayTextBox.Text += String.Format("{0:D2}:{1:D2}:{2:D2}", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);

Форматирование строк в C++:

SPRINTF

#include <stdio.h>

Int sprintf(buffer, format-string[, argument...]); char *buffer;

память для хранения вывода char *format-string; строка управления форматом

Описание.

Функция sprintf форматирует и запоминает наборы символов и значений в buffer. Каждый аргумент argument (если он есть), преобразуется и выводится согласно соответствующей спецификации формата в format-string. Format-string состоит из порядковых символов и имеет ту же самую форму и функцию, что аргумент format-string для функции printf. Смотрите функцию printf для описания format-string и аргументов.

Возвращаемое значение.

Функция sprintf возвращает количество символов, записанных в buffer. См. также fprintf, printf, sscanf.

Пример.

#include <stdio.h>

char buffer[200];

int i, j; double fp; char *s = "computer"; char c;

/* форматирует и печатает различные данные */

j = sprintf(buffer, "%s\n", s); j + = sprintf(buffer+j, "%c\n", c); j + = sprintf(buffer+j, "%d\n",i); j + = sprintf(buffer+j, "%f\n",fp);.

Эффективность формирования строк и класс StringBuilder в C#:

При операции s += t остаются три объекта: s, s (новое = s+t) и t. При множественных операциях сложения строк получается много лишних объектов. Для решения этой проблемы и более эффективного использования ресурсов существует класс StringBuilder в C#.

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

Большинство методов, изменяющих экземпляр данного класса, возвращают ссылку на тот же экземпляр. Поскольку ссылка на экземпляр возвращается, имеется возможность вызвать метод или свойство по ссылке. Это удобно при написании отдельного оператора, соединяющего последовательные операции.

Емкостью StringBuilder считается максимальное количество знаков, которое экземпляр может хранить в любой момент времени. Емкость больше или равна длине строкового представления значения экземпляра. Емкость можно увеличить или уменьшить с помощью свойства Capacity или метода EnsureCapacity, но она не может быть меньше значения свойства Length.

Связанные с реализацией значения по умолчанию используются, если при инициализации экземпляра StringBuilder емкость не указана или указана максимальная емкость.

Вопросы производительности

Методы Concat и AppendFormat объединяют новые данные с существующим объектом String или StringBuilder. Операция объединения объекта String всегда создает новый объект из существующей строки и новых данных. Объект StringBuilder обеспечивает размещение в буфере объединенных новых данных. Новые данные добавляются в конец буфера, если есть доступное место, в противном случае выделяется буфер большего размера, данные из исходного буфера копируются в новый буфер, когда новые данные добавляются в новый буфер.

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

Подробное описание методов и свойств - http://msdn.microsoft.com/ru-ru/library/system.text.stringbuilder.aspx

Пример:

static void Main()

{ // Create a StringBuilder that expects to hold 50 characters.

// Initialize the StringBuilder with "ABC".

StringBuilder sb = new StringBuilder("ABC", 50);

// Append three characters (D, E, and F) to the end of the StringBuilder.

sb.Append(new char[] { 'D', 'E', 'F' });

// Append a format string to the end of the StringBuilder.

sb.AppendFormat("GHI{0}{1}", 'J', 'k');

// Display the number of characters in the StringBuilder and its string.

Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString());

// Insert a string at the beginning of the StringBuilder.

sb.Insert(0, "Alphabet: ");

// Replace all lowercase k's with uppercase K's.

sb.Replace('k', 'K');

// Display the number of characters in the StringBuilder and its string.

Console.WriteLine("{0} chars: {1}", sb.Length, sb.ToString()); }