Читаем QT 4: программирование GUI на С++ полностью

В строке 13 указатель устанавливается в нулевое значение. С++ не имеет ключевого слова для представления указателя, который не ссылается ни на один объект; вместо этого мы используем значение 0 (или символическую константу NULL, которая разворачивается в 0). Попытка применения нулевого указателя приведет к краху приложения с выводом такого сообщения об ошибке, как «Segmentation fault» (ошибка сегментации), «General protection fault» (общая ошибка защиты) или «Bus error» (ошибка шины). Применяя отладчик, можно найти строку программного кода, которая приводит к краху.

В конце функции объект alpha содержит пару координат (1.0, 2.5), а объект beta — (4.0,4.5).

Указатели часто используются для хранения объектов, память для которых выделяется динамически с помощью оператора new. Используя жаргон С++ можно сказать, что эти объекты распределяются в «куче», в то время как локальные переменные (т.е. переменные, определенные внутри функции) хранятся в «стеке».

Ниже приводится фрагмент программного кода, иллюстрирующий динамическое распределение памяти при помощи оператора new:

01 #include "point2d.h"

02 int main()

03 {

04 Point2D *point = new Point2D;

05 point->setX(1.0);

06 point->setY(2.5);

07 delete point;

08 return 0;

09 }

Оператор new возвращает адрес памяти для нового распределенного объекта. Мы сохраняем адрес в переменной указателя и обращаемся к объекту через этот указатель. Поработав с объектом, мы возвращаем занимаемую им память, используя оператор delete. В отличие от Java и C#, сборщик мусора отсутствует в С++; динамически распределяемые объекты должны явно освобождать занимаемую ими память при помощи оператора delete, когда они становятся больше ненужными. В главе 2 описывается механизм родственных связей Qt, который значительно упрощает управление памятью в программах, написанных на С++.

Если не вызвать оператор delete, память остается занятой до тех пор, пока не завершится программа. Это не создаст никаких проблем в приведенном выше примере, потому что память выделяется только для одного объекта, однако в программе, в которой постоянно создаются новые объекты, это может привести к нехватке машинной памяти. После удаления объекта переменная указателя по-прежнему будет хранить адрес объекта. Такой указатель является «повисшим указателем» и не должен использоваться для обращения к объекту. Qt предоставляет «умный» указатель QPointer, который автоматически устанавливает себя в 0, если удаляется объект QObject, на который он ссылается.

В приведенном выше примере мы вызывали стандартный конструктор и функции setX() и setY() для инициализации объекта. Вместо этого можно было использовать конструктор с двумя параметрами:

Point2D *point = new Point2D(1.0, 2.5);

Кроме того, мы могли бы распределить объект в стеке следующим образом:

Point2D point;

point.setX(1.0);

point.setY(2.5);

Распределенные таким образом объекты автоматически освобождаются в конце блока, в котором они появляются.

Если мы не собираемся модифицировать объект при помощи указателя, можно объявить указатель как константный. Например:

const Point2D *ptr = new Point2D(1.0, 2.5);

double x = ptr->x();

double у = ptr->y();

// НЕ БУДЕТ КОМПИЛИРОВАТЬСЯ

ptr->setX(4.0);

*ptr = Point2D(4.0, 4.5);

Константный указатель ptr можно использовать лишь для вызова константных функций-членов, например x() и y(). Признаком хорошего стиля является объявление указателей константными, когда нет намерения модификации объекта с их помощью. Более того, если сам объект является константным, ничего не остается, кроме использования константного указателя для хранения его адреса. Применение ключевого слова const предоставляет компилятору информацию, позволяющую обнаруживать ошибки на ранних этапах и повысить производительность. C# имеет ключевое слово const с очень похожими свойствами. Ближайшим эквивалентом в Java является ключевое слово final, однако оно лишь защищает переменные от операций присваивания, но не от вызова «неконстантных» функций—членов объекта.

Указатели могут использоваться со встроенными типами так же, как с классами. Используемый в выражении унарный оператор * возвращает значение объекта, на который ссылается указатель. Например:

int i = 10;

int j = 20;

int *p = &i

int *q = &j

cout << *p << " equals 10" << endl;

cout << *q << " equals 20" << endl;

*p = 40;

cout << i << " equals 40" << endl;

p = q;

*p = 100;

Перейти на страницу:

Похожие книги

C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных
C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных