Работает точно так же. Прочитал внимательно 5.2.5 Class member access [expr.ref].
Ни слова о нулевом указателе. Нельзя ли подробнее, что же я упустил?
Kaa>Ну, и про идентификаторы тоже... Все, что начинается с _<Большая латинская> — зарезервировано.
Вы про auto_pod::_PODSize? Он начинается с маленькой латинской буквы.
Указанное Вами правило (17.4.3.1.2) относится только к глобальным именам.
Или у нас стандарты разные
Здравствуйте, Блудов Павел, Вы писали:
Kaa>>разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).
БП>Прочитал внимательно 5.2.5 Class member access [expr.ref]. БП>Ни слова о нулевом указателе. Нельзя ли подробнее, что же я упустил?
1.9/4, к примеру, говорит, что разыменование нулевого указателя порождает неопределенное поведение.
БП>Указанное Вами правило (17.4.3.1.2) относится только к глобальным именам.
Нет, стандарты у нас одинаковые. Тут я не прав. Спасибо.
Здравствуйте, Кодт, Вы писали:
К>Вот, достало ловить ошибки с неинициализованными членами больших классов, вида
... skip() ... К>[/c]
А как можно модифицировать этот замечательный класс, что бы можно было писать нечто
auto_value<int> i = 0;
auto_value<int> j = i;
А то ругается на это, говорит : error C2440: 'initializing' : cannot convert from 'class auto_value<int,0>' to 'class auto_value<int,0>'
No copy constructor available for class 'auto_value<int,0>'
без этого в конструкторах копии приходится писать
Kaa>Такой код может быть написан только в реализации стандартной библиотеки, или в компиляторно-зависимой библиотеке. Для всего остального разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).
Он там и написан. <cstddef>:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
18.1.5
The macro offsetof accepts a restricted set of type arguments in this International Standard. type shall be a POD structure or a POD union (clause 9). The result of applying the offsetof macro to a field that is a static data member or a function member is undefined.
Это, конечно, лишает массы удобств. Но и необходимо только для тяжелых классов, которые лучше сконструировать и не трогать.
А для легких, с конструктором по умолчанию, и которым присваивать можно:
class Foo
{
Bar bar;
Foobar foobar;
struct AllMyStaff
{
AllMyStaff()
{
bar = Bar(barParam);
foobar = Foobar(foobarParam);
}
} allMyStaff;
};
Кроме того конструктор AllMyStaff ( хорошего названия я так и не придумал никогда, кто придумает скажите, а то уже надоели всякие X и прочие глупости ) можно сделать с параметром. Забыть его теперь нельзя, но можно передать нужные параметры.
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, Рома Мик, Вы писали:
ME>[]
РМ>>А для легких, с конструктором по умолчанию, и которым присваивать можно:
РМ>>
РМ>> }
РМ>> } allMyStaff;
РМ>>};
РМ>>
ME>Ты пробовал эту херню скомпилить хоть разок? Советую попробовать.
Пробовал, но достаточно давно. Потому забыл подробности. Это довольно редко нужный код, т.к. редко нельзя унаследоваться от AllMyStaff. В этом варианте надо передавать this в конструктор AllMyStaff.
БП>Хотя в этом случае, нилем имеет смысл прописать только первые 9-ть байт. БП>Есть идеи?
Нет никаких идей. Это — суровая правда жизни
struct aa
{
__int8 i2;
__int64 i1;
};
Здесь размер — тоже 16 и надо инициализировать все 16 байт. Как отличить эти два случая? Можно, конечно, тупо и грязно использовать #pragma pack, но на Intel это приведет к резкой деградации производительности, а на других платформах (Sun, SGI, если там есть аналогичная прагма) — вообще не будет работать, там сразу "автобусная ошибка" и до свидания...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Очень хорошая идея , но имеет небольшой недостаток — переменный инициализируются полько в начале , а что если я хочу сбросить все переменные в начальное состояние ?
Есть решение но с использованием макросов:
template<class T, T i = T()>
class auto_value
{
T t_;
public:
typedef T data_t;
typedef auto_value& self_t;
// конструктор по умолчанию - главное достоинство этой тулзыinline auto_value() : t_(i) {}
// конструктор с 1 параметром (в том числе - конструктор копирования)template< class V >
inline auto_value(V v) : t_(v) {}
// доступ к данномуinline const T& data() const { return t_; }
inline T& data() { return t_; }
// считается, что исходный тип - простойinline operator T () const { return t_; }
inline operator T& () { return t_; }
// операторы присваиванияtemplate< class V > inline self_t operator = (V v) { t_ = v; return *this; }
template< class V > inline self_t operator += (V v) { t_ += v; return *this; }
template< class V > inline self_t operator -= (V v) { t_ -= v; return *this; }
template< class V > inline self_t operator *= (V v) { t_ *= v; return *this; }
template< class V > inline self_t operator /= (V v) { t_ /= v; return *this; }
template< class V > inline self_t operator %= (V v) { t_ %= v; return *this; }
template< class V > inline self_t operator &= (V v) { t_ &= v; return *this; }
template< class V > inline self_t operator |= (V v) { t_ |= v; return *this; }
template< class V > inline self_t operator ^= (V v) { t_ ^= v; return *this; }
template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; }
template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; }
// по умалчаниюinline void default_() { t_=i; }
};
#define BEGIN_AUTO_MAP() \
public: \
void default_() \
{
#define AUTO_VALUE(v) \
v.default_();
#define END_AUTO_MAP() \
}
class Test
{
auto_value<int,5> i;
auto_value<char,'a'> c;
BEGIN_AUTO_MAP()
AUTO_VALUE(i)
AUTO_VALUE(c)
END_AUTO_MAP()
};
void main()
{
Test test;
test.i=10;
test.c='f';
test.default_();
}
Здравствуйте, Кодт, Вы писали:
К>Вот, достало ловить ошибки с неинициализованными членами больших классов
Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память.
Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.
Здравствуйте, MShura, Вы писали:
MS>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память. MS>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.
Во-первых, ты для каждого своего класса вынужден совершить ряд излишних телодвижений.
Во-вторых, не всегда это можно сделать — например, если я пишу кокласс с использованием ATL — там всегда используется единственный конструктор (без параметров) и к тому же класс заведомо не финальный: создается CComObject<MyClass> который является потомком.
Что же мне, ATL переписывать, чтобы там new память чистил?
Любая ситуация с наследованием от данного класса — и все, приплыли.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, MShura, Вы писали:
MS>>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память. MS>>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.
К>Во-первых, ты для каждого своего класса вынужден совершить ряд излишних телодвижений. К>Во-вторых, не всегда это можно сделать — например, если я пишу кокласс с использованием ATL — там всегда используется единственный конструктор (без параметров) и к тому же класс заведомо не финальный: создается CComObject<MyClass> который является потомком. К>Что же мне, ATL переписывать, чтобы там new память чистил? К>Любая ситуация с наследованием от данного класса — и все, приплыли.
Насколько я помню, если оператор new есть у одного из базовых классов, то для производных он также будет вызываться (соответственно размер требуемой памяти будет передаваться нужный).
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, MShura, Вы писали:
MS>>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память. MS>>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.
Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо.
Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.
Здравствуйте, MShura, Вы писали:
MS>Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо. MS>Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.
А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто...
Кроме того, auto_value позволяет инициализировать переменные любым нужным значением
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, MShura, Вы писали:
MS>>Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо. MS>>Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.
К>А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто...
А в чем проблема?Основное условие — все экземпляры/подэкземпляры должны создаваться через new.
Это так сказать цена за удобство.
К>Кроме того, auto_value позволяет инициализировать переменные любым нужным значением
Для таких целей тот подход бесполезен. К>