[Bug][VC] Cнова?
От: _nn_  
Дата: 30.05.10 11:48
Оценка: 35 (2) -1 :))) :))) :))) :)
Простой код

struct base
{
  int i;
  char c;
};

struct derived : base
{
  double d;
};

#include <stdio.h>

int main()
{  
 base b = base();
 printf("b.i - %d\n", b.i);
 printf("b.c - %d\n", (int)b.c);

 derived d = derived();
 printf("d.i - %d\n", d.i);
 printf("d.c - %d\n", (int)d.c);
 printf("d.d - %f\n", d.d);
}


G++ 4.4.3

b.i — 0
b.c — 0
d.i — 0
d.c — 0
d.d — 0.00000


VC 2008, 2010

b.i — 0
b.c — 0
d.i — -858993460
d.c — -52
d.d — -925596....


Если не наследоваться, то работает нормально:
struct derived /* : base*/
{
  base b;
  double d;
};


А также работает через new
derived* pd = new derived();
derived& d = *pd;

...


К счастью нашлось более элегантное решение через placement new:
derived d;
new (&d) derived();


Тут можно возразить, и посоветовать memset.
Однако memset не будет хорошо работать для классов с нетривиальными конструкторами.

Если добавить класс с нетривиальным конструктором, VC конкретно лажает:
struct nontrivial
{
  nontrivial() : member(4) {}
  ~nontrivial() {}

  int member;
};

struct base
{
  int i;
  char c;

  nontrivial n;
};

struct derived : base
{
  double d;
};

#include <stdio.h>
#include <new>

int main()
{  
 base b = base();
 printf("b.i - %d\n", b.i);
 printf("b.c - %d\n", (int)b.c);
 printf("b.n.member - %d\n", b.n.member);

 derived d = derived();
 new (&d) derived(); // Workaround ??
 printf("d.i - %d\n", d.i);
 printf("d.c - %d\n", (int)d.c);
 printf("d.d - %f\n", d.d);
}


Вывод

b.i — -858993460
b.c — -52
b.n.member — 4
d.i — -858993460
d.c — -52
d.d — -925596....


Тут уже ничего не помогает. Даже new base() не работает.

В общем какой-то баг с инициализацией.
Берегитесь
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: [Bug][VC] Cнова?
От: SleepyDrago Украина  
Дата: 01.06.10 20:35
Оценка: +1 -1
Здравствуйте, Кодт, Вы писали:
...
К>Любой нетривиальный конструктор, пусть и неявно определённый, — это некая функция. И вот в эту функцию пожадничали вставить лишний memset перед инициализацией отдельных полей. А уж тем более — почленное обнуление.
...
если бы вставили — им бы надо было ноги оторвать по самые уши. Я когда пул себе делал на каждое взаимодействие я чуть крышей не навернулся пока сумел эти мемсеты искоренить из кода к чертям собачьим. Помогло только объявить пустой конструктор у всех структур. Так что любителям неявных неотключаемых мемсетов срочно стоит искать себе платформу побезопаснее
имхо должно быть 2 разных синтаксиса вместо этой идиотии когда одна и та же запись Т() означает 2 разные вещи. Сделали бы
T x = {};

или еще что нибудь и не парили людям мозг этими "смысловыми перегрузками".
Re[5]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 09:45
Оценка: 5 (1)
Инициализация полей нужна для избежания undefined behavior при копировании:

T const &t1 = T(); // разрешено копирование (C++03)
T t2 = T(); // разрешено копирование
Re[11]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 12:41
Оценка: 1 (1)
_nn>Должны обнулятся остальные члены класса или нет ?

По действующему стандарту — да. А по новым правилам начиная с N2798 здесь вообще потребуется полная zero-инициализация.
Re: [Bug][VC] Cнова?
От: Alximik509 Россия  
Дата: 30.05.10 12:43
Оценка: +1
Чета я нифига не понял.. В чем баг то?
или это типо шутка?
Re: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 09:14
Оценка: -1
Здравствуйте, _nn_, Вы писали:

<>

Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.
Тогда как для не-POD-типов — это default-initialization.
Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
Отсюда и мусор.

Статические же объекты всегда сначала обнуляются, а потом уже инициализируются в рантайме. (Компилятор вправе оптимизировать это, сразу инициализировав статическое хранилище константами).
Кстати, эта двухступенчатая инициализация является источником unspecified behavior (а то и undefined, если постараться ) при обращении к статическим объектам.

С вашего позволения, не приведу цитаты стандарта, а только укажу параграфы
— 3.6.2 Start and termination / Initialization of non-local objects
— 8.5:5 Initializers / zero-, default-, value-initializer
— 12.6.2:4 Special member functions / Initializing bases and members
Впрочем, последнее как раз и стоит процитировать.

If a given nonstatic data member or base class is not named by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then
If the entity is a nonstatic data member of (possibly cv-qualified) class type (or array thereof) or a base class, and the entity class is a non-POD class, the entity is default-initialized (8.5). If the entity is a nonstatic data member of a const-qualified type, the entity class shall have a user-declared default constructor.
Otherwise, the entity is not initialized. If the entity is of const-qualified type or reference type, or of a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of a const-qualified type, the program is ill-formed.


Вот такая грабля.
Перекуём баги на фичи!
Re[3]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 10:20
Оценка: -1
Здравствуйте, ilvi, Вы писали:

К>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>Тогда как для не-POD-типов — это default-initialization.
К>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>Отсюда и мусор.

I>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

Сказано же: рекурсивно вызывается либо default-initialization (если элемент — не-POD), либо ничего не вызывается.
Итого, если развернуть всё дерево, ни один член не будет инициализирован, если это не делается явно.

Да, это подлянка, зашитая в стандарт, ради того, чтобы не платить за то, что не прошено.
Вот если бы в языке было две формы конструктора "без параметров" — минимальный и тотальный...
Перекуём баги на фичи!
Re: [Bug][VC] Cнова?
От: Caracrist https://1pwd.org/
Дата: 30.05.10 12:02
Оценка:
Здравствуйте, _nn_, Вы писали:


__>VC 2008, 2010

VC 2005 same shit (debug)
__>

__>b.i — 0
__>b.c — 0
__>d.i — -858993460
__>d.c — -52
__>d.d — -925596....


2005 release:

b.i — 0
b.c — 0
d.i — 4206624
d.c — 40
d.d — 0.000000


__>Берегитесь
~~~~~
~lol~~
~~~ Single Password Solution
Re: [Bug][VC] Cнова?
От: Caracrist https://1pwd.org/
Дата: 30.05.10 12:18
Оценка:
Здравствуйте, _nn_, Вы писали:


__>Если добавить класс с нетривиальным конструктором, VC конкретно лажает:



и не только VC:
http://codepad.org/3iS30XBJ (g++ 4.1.2)

b.i — 0
b.c — 36
b.n.member — 4
d.i — 1076296996
d.c — 36
d.d — 0.000000
d.n.member — 4




__>В общем какой-то баг с инициализацией.

__>Берегитесь
~~~~~
~lol~~
~~~ Single Password Solution
Re: [Bug][VC] Cнова?
От: rm822 Россия  
Дата: 30.05.10 12:44
Оценка:
Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [Bug][VC] Cнова?
От: Ops Россия  
Дата: 30.05.10 13:11
Оценка:
Здравствуйте, _nn_, Вы писали:

<...>

__>В общем какой-то баг с инициализацией.


Можно ссылочку на стандарт, где написано, что там должны быть нули? Я просто давно в это не вникал, т.к. не использую переменные до их явной инициализации.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 13:35
Оценка:
Здравствуйте, rm822, Вы писали:

R>Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС


А чем тогда является: derived d = derived(); ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[2]: [Bug][VC] Cнова?
От: _nn_  
Дата: 30.05.10 13:44
Оценка:
Здравствуйте, rm822, Вы писали:

R>Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС


Тогда почему тут печатает разные числа ?

#include <stdio.h>

#include <string>

struct check
{
    std::string s;
    int i;
};

static check c = check();
static check d;

struct basecheck2
{
    int i;
};

struct check2 : basecheck2
{
    char c;
};

static check2 c2 = check2();
static check2 d2;

int main()
{
  printf("%d\n", c.i);
  printf("%d\n", c2.i);
}


0
-858993460

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 14:06
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Тогда почему тут печатает разные числа ?


Потому что check -- не POD.
Re: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 14:14
Оценка:
Здравствуйте, _nn_,

8.5:9

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a non-static object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

Re: [Bug][VC] Cнова?
От: Masterkent  
Дата: 30.05.10 14:15
Оценка:
Это, в общем-то, известный баг VC++ — он, похоже, не учитывает правила value-инициализации C++03, а следует устаревшему стандарту 98-го года.
Re[2]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 30.05.10 14:29
Оценка:
quodum:

Q>8.5:9

Q>

If no initializer is specified for an object [...]

Это тут вообще не при чём. См. C++03 — 5.2.3/2 и 8.5/5.
Re[4]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 14:37
Оценка:
Здравствуйте, quodum, Вы писали:

Q>Здравствуйте, _nn_, Вы писали:


__>>Тогда почему тут печатает разные числа ?


Q>Потому что check -- не POD.


Давайте усложним и добавим к примеру создание объекта:

struct basecheck2
{
    int i;
};
static basecheck2 b = basecheck2();
...
//и вывод его на печать

  printf("%d\n", c.i);
  printf("%d\n", c2.i);
  printf("%d\n", b.i);


0
-858993460
0


Это вс2010. basecheck2 — POD и что теперь?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[3]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 14:41
Оценка:
Здравствуйте, _nn_, Вы писали:

codepad по другому глючит. добавил вывод для объекта типа basecheck2.
http://codepad.org/waCq7obR

#include <stdio.h>

#include <string>

struct check
{
    std::string s;
    int i;
};

static check c = check();
static check d;

struct basecheck2
{
    int i;
};

struct check2 : basecheck2
{
    char c;
};

static check2 c2 = check2();
static check2 d2;

static basecheck2 b = basecheck2();

int main()
{
  printf("%d\n", c.i);
  printf("%d\n", c2.i);
  printf("%d\n", b.i);
}



Output:
134543672
0

0

... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[3]: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 23:10
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>quodum:


Q>>8.5:9

Q>>

If no initializer is specified for an object [...]

M>Это тут вообще не при чём. См. C++03 — 5.2.3/2 и 8.5/5.

А, точно.
Re[2]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 31.05.10 10:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>Тогда как для не-POD-типов — это default-initialization.
К>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>Отсюда и мусор.

Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?
Не должна ли рекурсивно для всех членов вызваться value-initialization ?
Re[3]: [Bug][VC] Cнова?
От: kvser  
Дата: 31.05.10 10:15
Оценка:
Здравствуйте, ilvi, Вы писали:

I>Здравствуйте, Кодт, Вы писали:


К>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>Тогда как для не-POD-типов — это default-initialization.
К>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>Отсюда и мусор.

I>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

http://rsdn.ru/Forum/Info/FAQ.cpp.newnnew.aspx
Автор: Андрей Тарасевич
Дата: 07.12.04
Re[4]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 31.05.10 10:26
Оценка:
Здравствуйте, kvser, Вы писали:

K>Здравствуйте, ilvi, Вы писали:


I>>Здравствуйте, Кодт, Вы писали:


К>>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>>Тогда как для не-POD-типов — это default-initialization.
К>>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>>Отсюда и мусор.

I>>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

K>http://rsdn.ru/Forum/Info/FAQ.cpp.newnnew.aspx
Автор: Андрей Тарасевич
Дата: 07.12.04



Если это не-POD-класс-тип без явно объявленного конструктора, то в первом случае будет рекурсивно применена value-initialization к каждому подобъекту этого класса (что при этом получится — зависит о типов этих подобъектов),


Первый случай там

new T();


Или я под вечер чего-то не понимаю уже?
Re[2]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 18:15
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Это, в общем-то, известный баг VC++ — он, похоже, не учитывает правила value-инициализации C++03, а следует устаревшему стандарту 98-го года.


Аха, это разница в пункте 5.2.3 «Explicit type conversion (functional notation)» :2 стандарт (1998)(2003)

The expression T(), where T is a simple-type-specifier (7.1.5.2) for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by default-initialization which is value-initialized (8.5; no initialization is done for the void() case).
[Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are ignored when determining the type of the resulting rvalue (3.10). ]

и в пункте 12.6 «Initialization» :1

When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the
initializer has the form (), the object is initialized as specified in 8.5. [Note: if the class is a non-POD, it is default-initialized.] The object is default-initialized if
there is no initializer, or value-initialized if the initializer is ().


Тем не менее, 12.1 «Constructors» :7 — обе редакции говорят одинаково

An implicitly-declared default constructor for a class is implicitly defined when it is used to create an object
of its class type (1.8). The implicitly-defined default constructor performs the set of initializations of the
class that would be performed by a user-written default constructor for that class with an empty meminitializer-
list (12.6.2) and an empty function body.
If that user-written default constructor would be illformed,
the program is ill-formed. Before the implicitly-declared default constructor for a class is implicitly
defined, all the implicitly-declared default constructors for its base classes and its nonstatic data members
shall have been implicitly defined. [Note: an implicitly-declared default constructor has an exceptionspecification
(15.4). ]

После чего смотрим на 12.6.2:4, который я уже приводил.

Разделительная черта в стандарте (в обеих редакциях) проведена не по тривиальному/нетривиальному дефолтному конструктору, а по определённому пользователем или нет.
8.5 «Initializers» :6

To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is
called
(and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member
and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized


Однако, gcc 4.3 (как и VC) смотрит именно на тривиальность/нетривиальность.
struct A { int x; };
struct B : A { int y; };
struct C : A { int z; virtual void foo() {} };

int main()
{
  A a1;       // VC, gcc: not initialized
  A a2 = A(); // VC, gcc: value-initialize => zero-initialize

  B b1;       // VC, gcc: default ctor => not initialized
  B b2 = B(); // VC: default ctor => not initialized
              // gcc: value-initialize => zero-initialize

  C c1;       // VC, gcc: default ctor => not initialized
  C c2 = C(); // VC, gcc: default ctor => not initialized
              // vfptr они, разумеется, установили
}

Баг gcc? Или дефект стандарта?
Перекуём баги на фичи!
Re[3]: [Bug][VC] Cнова?
От: alexeiz  
Дата: 31.05.10 18:29
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Masterkent, Вы писали:


M>>Это, в общем-то, известный баг VC++ — он, похоже, не учитывает правила value-инициализации C++03, а следует устаревшему стандарту 98-го года.


К>Аха, это разница в пункте 5.2.3 «Explicit type conversion (functional notation)» :2 стандарт (1998)(2003)

...
К>и в пункте 12.6 «Initialization» :1
...
К>Тем не менее, 12.1 «Constructors» :7 — обе редакции говорят одинаково
...
К>После чего смотрим на 12.6.2:4, который я уже приводил.
...

Павел Кузнецов отметил, что 12.6.2/4 здесь неприменимо.

Для гарантированной инициализации можно пользоваться boost.value_init
Re[4]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 19:16
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Павел Кузнецов отметил, что 12.6.2/4 здесь неприменимо.


Я, как бы, согласен с Павлом.
Однако подчёркиваю: разделение проведено по наличию-отсутствию пользовательского конструктора. А если конструктор нетривиальный, но неявно определённый — то фигня, тем не менее, наблюдается и у gcc.
Перекуём баги на фичи!
Re[4]: [Bug][VC] Cнова?
От: Тролль зеленый и толстый  
Дата: 31.05.10 19:58
Оценка:
Чей-то я не понял, а как же value initialization?
Re[5]: [Bug][VC] Cнова?
От: Тролль зеленый и толстый  
Дата: 31.05.10 20:05
Оценка:
А, пардон, понял. Тогда как объяснить поведение GCC?
Re[6]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 01.06.10 08:54
Оценка:
Здравствуйте, Тролль зеленый и толстый, Вы писали:

ТЗИ>А, пардон, понял. Тогда как объяснить поведение GCC?


Очень просто.
value initialization примитивно трактуется как zero initialization, и реализуется так же: memset(&dst,sizeof(dst),0).
Причём это действие выполняется на месте создания переменной (а для статического хранилища — вообще операционной системой).
Любой нетривиальный конструктор, пусть и неявно определённый, — это некая функция. И вот в эту функцию пожадничали вставить лишний memset перед инициализацией отдельных полей. А уж тем более — почленное обнуление.

Кстати, воспроизводится для неявных конструкторов
— с нетривиальными членами
— с виртуальными функциями
И почему-то не воспроизводится для виртуального наследования
http://codepad.org/0s8tKaDK
Перекуём баги на фичи!
Re[3]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 01.06.10 23:00
Оценка:
Кодт:

К>Баг gcc? Или дефект стандарта?


Имеет место и то и другое. Но т.к. open-std.org лежит, а этот форум опять глючит, подробное разъяснение я здесь предоставить не могу.
Re[8]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 01.06.10 23:41
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>имхо должно быть 2 разных синтаксиса вместо этой идиотии когда одна и та же запись Т() означает 2 разные вещи. Сделали бы

SD>
SD>T x = {};
SD>

SD> или еще что нибудь и не парили людям мозг этими "смысловыми перегрузками".

Смысловые перегрузки, действительно, раздражают.
А в данном случае 2 синтаксиса уже есть. Они неочевидные, и это ещё один камень в огород Страуструпа и Комитета.
// no init (POD) / default init (non-POD)
T x;
T* px = new T;

// value=zero init (POD & POD-like) / default init (non-POD)
T x = T();
T* px = new T();


Кстати, чтобы форсировать default init / no init, достаточно сделать такое
template<class T>
struct Holder
{
  T data;
  Holder() {}
  operator T&() { return data; ]
  operator T const&() { return data; }
  // для панков
  T* operator&() { return &data; }
  T const* operator&() { return &data; }
};

То есть, не лепить пустые конструкторы во все структуры, а сделать внешнюю обёртку.
Перекуём баги на фичи!
Re[4]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 01.06.10 23:44
Оценка:
Здравствуйте, Masterkent, Вы писали:

К>>Баг gcc? Или дефект стандарта?


M>Имеет место и то и другое. Но т.к. open-std.org лежит, а этот форум опять глючит, подробное разъяснение я здесь предоставить не могу.


То есть, он уже занесён в багтрекер? Ну, хоть то радует.
А что случилось с open-std.org?
Перекуём баги на фичи!
Re[9]: [Bug][VC] Cнова?
От: _nn_  
Дата: 02.06.10 06:47
Оценка:
Здравствуйте, Кодт, Вы писали:

К>То есть, не лепить пустые конструкторы во все структуры, а сделать внешнюю обёртку.


Как было уже указанно, boost.value_initialized делает эту работу.

Как все же у него получается ?
Подглядев код, он делает примерно следующее:
char buffer[sizeof(T)];

memset(&buffer[0], 0, sizeof(T));
new (&buffer[0]) T();


Явный вызов memset приводит к обнулению всех полей.
А вызов конструктора вызовет конструкторы по умолчанию у членов класса у которых они есть.
Таким образом получаем нужное решение, хотя ,конечно, могли бы в стандарте обойти это более элегантно.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[10]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 02.06.10 07:28
Оценка:
Здравствуйте, _nn_, Вы писали:

К>>То есть, не лепить пустые конструкторы во все структуры, а сделать внешнюю обёртку.

__>Как было уже указанно, boost.value_initialized делает эту работу.

Он делает прямо противоположную работу. SleepyDrago жаловался, что ему эти memset'ы мешают (просадка производительности, видимо).
Перекуём баги на фичи!
Re[11]: [Bug][VC] Cнова?
От: _nn_  
Дата: 02.06.10 07:49
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, _nn_, Вы писали:


К>>>То есть, не лепить пустые конструкторы во все структуры, а сделать внешнюю обёртку.

__>>Как было уже указанно, boost.value_initialized делает эту работу.

К>Он делает прямо противоположную работу. SleepyDrago жаловался, что ему эти memset'ы мешают (просадка производительности, видимо).


Тогда нужны две версии класса, одна с memset-ом, если требуется в компиляторе, а другая гарантированно только с конструктором.

Есть тикет об этом в бусте, но что-то в 1.43 не добавили патч.
https://svn.boost.org/trac/boost/ticket/3869
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 09:42
Оценка:
К>То есть, он уже занесён в багтрекер?

ХЗ, я не интересуюсь багтрекером GNU C++. Но GNU C++ 4.5 уже, вроде, всё нормально обнуляет.
Re[5]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 09:43
Оценка:
К>А что случилось с open-std.org?

Два дня пробыл в отключке, сейчас заработал. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3083.html#508
Re[6]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 09:46
Оценка:
Напоминаю, что использование значения неинициализированного скалярного объекта (в том числе для копирования) влечёт undefined behavior (4.1/1).
Re[7]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 09:46
Оценка:
Если же компилятор способен соптимизировать лишнее копирование, то что ему мешает соптимизировать лишнее обнуление? Не вижу поводов для упрёков авторов правил.
Re[9]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 10:12
Оценка:
Кстати, о следующем способе value-инициализации почему-то мало кто вспоминает.

T var[1] = {}; // *var is value-initialized
Re[9]: [Bug][VC] Cнова?
От: SleepyDrago Украина  
Дата: 02.06.10 10:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, SleepyDrago, Вы писали:


SD>>имхо должно быть 2 разных синтаксиса вместо этой идиотии когда одна и та же запись Т() означает 2 разные вещи. Сделали бы

...
SD>> или еще что нибудь и не парили людям мозг этими "смысловыми перегрузками".

К>Смысловые перегрузки, действительно, раздражают.

К>А в данном случае 2 синтаксиса уже есть. Они неочевидные, и это ещё один камень в огород Страуструпа и Комитета.
...

вы вдвоем с _nn_ меня просто убиваете. Смотрите — если кому то нужна инициализация, то он может ее написать руками 1 раз на тип. Правильно? Они напихали мемсеты почти везде и при этом оставили дырку в виде выделения на стеке, которая все равно требует явного написания тех же самых инициализаторов, чтобы не писать их каждый раз. Имхо мне нужны оба вида инициализации и задающиеся непересекающимся между собой образом.

А теперь с приходом gcc 4.4 в редхате, который исправляет "баг" с принудительной value-инициализацией pod членов классов, наступает java головного мозга. Код который всю жизнь был совместим с C по структурам придется обкладывать пустыми конструкторами, чтобы ... он был совместим с С хотябы по поведению.

К>Кстати, чтобы форсировать default init / no init, достаточно сделать такое

К>
К>template<class T>
К>struct Holder
К>{
...
К>};
К>

К>То есть, не лепить пустые конструкторы во все структуры, а сделать внешнюю обёртку.

Шаблонные Холдеры это к санитарам. Туда же и с предложениями держать все структуры а-ля "прямоугольник" в двойном числе.
первое правило: "меньше кода — меньше проблем".
YMMV разумеется
Re[10]: [Bug][VC] Cнова?
От: _nn_  
Дата: 02.06.10 10:41
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Кстати, о следующем способе value-инициализации почему-то мало кто вспоминает.


M>
T var[1] = {}; // *var is value-initialized


А что должно происходит если есть член класса с конструктором ?
Должны обнулятся остальные члены класса или нет ?
struct nontrivial
{
  nontrivial() : member(4) {}
  ~nontrivial() {}

  int member;
};

struct base
{
  int i;
  char c;

  nontrivial n;
};

#include <stdio.h>


int main()
{  
  base bb[1] = {};
  base& b = bb[0];
  printf("b.i - %d\n", b.i);
  printf("b.c - %d\n", (int)b.c);
  printf("b.n.member - %d\n", b.n.member);
}


b.i — -858993460
b.c — -52
b.n.member — 4

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 02.06.10 12:14
Оценка:
Здравствуйте, _nn_, Вы писали:

M>>Кстати, о следующем способе value-инициализации почему-то мало кто вспоминает.

Потому что, какая разница, как value-инициализировать, =T() или ={}.
Последняя форма, правда, неприменимо к одиночным не-POD-ам, — только к массивам.

__>А что должно происходит если есть член класса с конструктором ?

Или если есть vfptr

__>b.i — -858993460


Это который компилятор? gcc 4.5? Аха, значит, недофиксали.
Перекуём баги на фичи!
Re[10]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 02.06.10 12:45
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>вы вдвоем с _nn_ меня просто убиваете. Смотрите — если кому то нужна инициализация, то он может ее написать руками 1 раз на тип. Правильно? Они напихали мемсеты почти везде и при этом оставили дырку в виде выделения на стеке, которая все равно требует явного написания тех же самых инициализаторов, чтобы не писать их каждый раз. Имхо мне нужны оба вида инициализации и задающиеся непересекающимся между собой образом.


Мы-то тут при чём? Мы в комитет по стандарту не входим. Вот они тебя пускай убивают, сколько влезет.
Нужны оба способа? Так оба способа и есть. Где там дырки на стеке???
struct Foo
{
  int x[1000];
  // и никаких конструкторов
};

void buz(const Foo&);

void bar()
{
  Foo f; // default/не инициализирована
  Foo g = {}; // value-инициализирована
  Foo h = Foo(); // value-инициализирована

  Foo *pf = new Foo; // default/не инициализирована
  Foo *ph = new Foo(); // value-инициализирована

  buz(Foo()); // value-инициализирована
  buz(Holder<Foo>()); // default/не инициализирована - вот здесь пришлось надстраиваться над синтаксисом
}


SD>А теперь с приходом gcc 4.4 в редхате, который исправляет "баг" с принудительной value-инициализацией pod членов классов, наступает java головного мозга. Код который всю жизнь был совместим с C по структурам придется обкладывать пустыми конструкторами, чтобы ... он был совместим с С хотябы по поведению.


В чём заключается совместимость? В том, чтобы поля были не инициализированы и содержали мусор? Можно считать, что нули — это такой специальный мусор.

SD>Шаблонные Холдеры это к санитарам. Туда же и с предложениями держать все структуры а-ля "прямоугольник" в двойном числе.

SD>первое правило: "меньше кода — меньше проблем".

Нафигачить пустые конструкторы в каждую структуру — это "меньше кода"?
Конечно, зависит от соотношения, сколько типов и сколько мест, где эти переменные создаются.
Я предположил, что "делал себе пул" означает, что был сделан некий шаблон, куда подставлялись разные типы структур. Из-за чего и пришлось пропатчить все структуры, чтобы мемсетами не замучило. Ну, так можно пропатчить непосредственно шаблон.

SD>YMMV разумеется


твоя гонка за скоростью, твой и mileage
Перекуём баги на фичи!
Re[12]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 12:48
Оценка:
К>Потому что, какая разница, как value-инициализировать, =T() или ={}.

Разница есть. T t = T(); потребует, чтобы T был copyable.
Re[12]: [Bug][VC] Cнова?
От: _nn_  
Дата: 02.06.10 12:53
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Это который компилятор? gcc 4.5? Аха, значит, недофиксали.

VC 2010.

GCC 4.4.3, 4.5 тоже не обнуляют.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[13]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 02.06.10 13:02
Оценка:
А вот Intel C++ 11.0.061 обнуляет, причём в соответствии с C++0x (если убрать ": member(4)", то member тоже обнуляется)
Re[11]: [Bug][VC] Cнова?
От: SleepyDrago Украина  
Дата: 02.06.10 13:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, SleepyDrago, Вы писали:


SD>>вы вдвоем с _nn_ меня просто убиваете. Смотрите — если кому то нужна инициализация, то он может ее написать руками 1 раз на тип. Правильно? Они напихали мемсеты почти везде и при этом оставили дырку в виде выделения на стеке, которая все равно требует явного написания тех же самых инициализаторов, чтобы не писать их каждый раз. Имхо мне нужны оба вида инициализации и задающиеся непересекающимся между собой образом.


К>Мы-то тут при чём? Мы в комитет по стандарту не входим. Вот они тебя пускай убивают, сколько влезет.

К>Нужны оба способа? Так оба способа и есть. Где там дырки на стеке???
Вы явно вошли в фанклуб любителей memset'а — вот этим и убиваете. Из-за того что людей которые "непожлобились" на левый мемсет стало много вообще и началась эта затея с _изменением_ семантики уже существующего кода на плюсах.
Дырка в их абстракции тотального обнуления. Его нет когда объект просто объявлен на стеке.

...

К>Нафигачить пустые конструкторы в каждую структуру — это "меньше кода"?

Этим структурам не нужна value initialization. Никогда. Поэтому из-за этих редисок этот код стал обязательным.

предложение бороться с шаблонами с помощью шаблонов принимается. К счастью это действительно редко нужно.

К>твоя гонка за скоростью, твой и mileage

ну это имхо единственное оправдание при использовании "портабельного ассемблера наших дней". Во всех остальных случаях те кто идут по более "декларативным" путям выигрывают во всем.
Re[12]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 02.06.10 14:29
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>Вы явно вошли в фанклуб любителей memset'а — вот этим и убиваете.


Ты видишь то, чего нет. Во всяком случае, в отношении меня.

Мне вообще пофиг на принудительные мемсеты. Если мне надо, я постараюсь написать так, чтобы оно гарантированно произошло, а если мне не надо, не забиваю себе голову. Какая разница, чем замусоривать, нулями или CDCDCDCD.

SD>Из-за того что людей которые "непожлобились" на левый мемсет стало много вообще и началась эта затея с _изменением_ семантики уже существующего кода на плюсах.


Это когда они не пожлобились на изменение семантики? В 1998 стандарте был дефект, — возможность трактовать как попало. Этот дефект постарались устранить (не до конца).

SD>Дырка в их абстракции тотального обнуления. Его нет когда объект просто объявлен на стеке.


В чём заключается дырка, я так и не понял.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.