Корректная инициализация
От: Аноним  
Дата: 15.09.02 09:58
Оценка:
Рассмотрим для примера такую задачу.
Имеется класс, для которого мы хотим иметь глобальный счетчик объектов этого класса. Простейшее решение очевидно:

struct T  
  {
  static int count;

  T() { count++; }
  ~T() { count--; }
  }

int T::count = 0;     // вот это (или аналогичный вариант со статической
                      // функцией-инициализатором) мне не нравится


но при этом мы должны "руками" установить начальное значение счетчика... что мне не нравится... ну и аналогичных ситуаций можно много придумать.

Вопрос: как можно организовать инициализацию статических членов класса, чтобы это не требовало явных действий человека, им пользующегося. Вот в Java вроде как можно при объявлении написать static int count = 0; и все ок...

Где-то читал, что все статические переменные и члены класса изначально инициализируются нулями. Эксперимент с доступными компиляторами это вроде подтверждает. Но, как я понимаю, это не оговорено стандартом и пользоваться этим нехорошо. Как быть?
Re: Корректная инициализация
От: Павел Кузнецов  
Дата: 15.09.02 10:30
Оценка:
Если нужна инициализация нулем, ничего, кроме определения int T::count, делать не нужно:

struct T {
  static int count;
  . . .
};

int T::count;


Стандарт гарантирует (3.6.2), что T::count, равно как и любой другой объект со static storage duration, в этом случае будет проинициализирован нулем.
<< J 1.0 alpha 4 >>
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Корректная инициализация
От: Аноним  
Дата: 15.09.02 11:05
Оценка:
Здравствуйте Павел Кузнецов, Вы писали:

ПК>Если нужна инициализация нулем, ничего, кроме определения int T::count, делать не нужно:


ПК>
ПК>struct T {
ПК>  static int count;
ПК>  . . .
ПК>};

ПК>int T::count;


ПК>Стандарт гарантирует (3.6.2), что T::count, равно как и любой другой объект со static storage duration, в этом случае будет проинициализирован нулем.


Спасибо... Буду внимательно изучать стандарт... А где его можно скачать (желательно на русском)?

Впрочем, все равно проблема остается — статический член нужно объявлять вне класса. Вообще непонятно, зачем так в языке сделано...
Re[3]: Корректная инициализация
От: Юнусов Булат Россия  
Дата: 15.09.02 12:57
Оценка: 11 (1)
Здравствуйте Аноним, Вы писали:

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


Тут уже много писалось что можно и внутри

struct FOO
{
    static int& GetRefCount() {
        static int refCount = 0; 
        return refCount;
    }
    FOO() {
        GetRefCount()++;
    }

    ~FOO() {
        GetRefCount()--;
    }
};
Re: Корректная инициализация
От: Андрей Тарасевич Беларусь  
Дата: 15.09.02 18:40
Оценка:
Здравствуйте Аноним, Вы писали:

А>Рассмотрим для примера такую задачу.

А>Имеется класс, для которого мы хотим иметь глобальный счетчик объектов этого класса. Простейшее решение очевидно:

А>
А>struct T  
А>  {
А>  static int count;

А>  T() { count++; }
А>  ~T() { count--; }
А>  }

А>int T::count = 0;     // вот это (или аналогичный вариант со статической
А>                      // функцией-инициализатором) мне не нравится

А>


А>но при этом мы должны "руками" установить начальное значение счетчика... что мне не нравится... ну и аналогичных ситуаций можно много придумать.


Если тебя не устраивает начальное значение 0, то устанваливать его тебе придется в любом случае "руками". Компилятор не телепат, он не может узнать, какое начальное значение тебе нужно.

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


Без явных действий человека все статические объекты инициализируются нулями.

А>Вот в Java вроде как можно при объявлении написать static int count = 0; и все ок...


Не понял. Здесь ты тоже явно указал инициализатор. Это тоже "явное действие человека". Чем этот вариант лучше, с твоей точки зрения, чем вариант с указанием инициализатора при определении переменной?

Кстати, для переменных целочисленных типов С++ тоже позволяет указывать инициализаторы при объявлении

struct T  
{
  static int count = 0;
  ...
};

int T::count;


Определение статического объекта (без инициализатора), если он используется в программе, при этом все равно надо делать. От этого в С++ никуда не уйдешь. (Правда, не совсем понятно, что рассматривается как "использование" объекта в программе).

А>Где-то читал, что все статические переменные и члены класса изначально инициализируются нулями. Эксперимент с доступными компиляторами это вроде подтверждает. Но, как я понимаю, это не оговорено стандартом и пользоваться этим нехорошо. Как быть?


Это оговорено стандартом.
Best regards,
Андрей Тарасевич
Re[2]: Корректная инициализация
От: MaximE Великобритания  
Дата: 15.09.02 19:08
Оценка:
Здравствуйте Андрей Тарасевич, Вы писали:

АТ>Определение статического объекта (без инициализатора), если он используется в программе, при этом все равно надо делать. От этого в С++ никуда не уйдешь. (Правда, не совсем понятно, что рассматривается как "использование" объекта в программе).


АТ>Это оговорено стандартом.


Вот что буквально говорит по этому поводу Маэстро

So why do these inconvenient restrictions exist? A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects. See D&E for an explanation of C++'s design tradeoffs.
...
You can take the address of a static member if (and only if) it has an out-of-class definition.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.