Сообщение Re[11]: memset(this, 0, sizeof(T)); от 23.11.2016 14:11
Изменено 23.11.2016 15:02 N. I.
smeeld:
NI>>А что такое нулевое значение для класса "с виртуальной таблицей и прочими причиндалами"?
S>То же самое, что и для классов без причиндал, то есть, нулевое значение, заданных определением класса полей.
Значение объекта и последовательность значений байт в его представлении — это не одно и то же.
S>Если конструкция {} приравнивает нулю эти поля классов без причиндал, почему это не распространяется на иные классы?
Во-первых, нуль нулю рознь. Даже у объекта POD типа "нулевое" значение может быть представлено ненулевыми байтами, а последовательность из нулевых байт может образовывать ненулевое значение. Например:
Выхлоп:
http://coliru.stacked-crooked.com/a/e5cea54dc6d9dd14
int S::* — это скалярный тип (все скалярные типы являются POD типами), и в данном случае компилятор для представления нулевого указателя на член использует последовательность значений байт, отличную от последовательности нулей.
Во-вторых, зачем подобной языковой конструкции заполнять что-то нулевыми байтами, если это не обеспечивает как минимум валидность значения инициализируемого объекта? Раз ты сам взялся определять способ конструирования валидного дефолтного значения через добавление соответствующего пользовательского конструктора — тебе и карты в руки.
NI>>А что такое нулевое значение для класса "с виртуальной таблицей и прочими причиндалами"?
S>То же самое, что и для классов без причиндал, то есть, нулевое значение, заданных определением класса полей.
Значение объекта и последовательность значений байт в его представлении — это не одно и то же.
S>Если конструкция {} приравнивает нулю эти поля классов без причиндал, почему это не распространяется на иные классы?
Во-первых, нуль нулю рознь. Даже у объекта POD типа "нулевое" значение может быть представлено ненулевыми байтами, а последовательность из нулевых байт может образовывать ненулевое значение. Например:
#include <cstring>
#include <iostream>
struct S
{
int i, j;
int S::*p;
};
#define PRINT_VALUE(expr) std::cout << #expr ": " << (expr) << std::endl;
int main()
{
S s;
s = S();
std::cout << std::boolalpha;
std::cout << "value-initialization" << std::endl;
PRINT_VALUE(s.p == nullptr);
PRINT_VALUE(s.p == &S::i);
PRINT_VALUE(s.p == &S::j);
std::memset(&s, 0, sizeof(s));
std::cout << "bytewise zeroing" << std::endl;
PRINT_VALUE(s.p == nullptr);
PRINT_VALUE(s.p == &S::i);
PRINT_VALUE(s.p == &S::j);
}Выхлоп:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
value-initialization
s.p == nullptr: true
s.p == &S::i: false
s.p == &S::j: false
bytewise zeroing
s.p == nullptr: false
s.p == &S::i: true
s.p == &S::j: falsehttp://coliru.stacked-crooked.com/a/e5cea54dc6d9dd14
int S::* — это скалярный тип (все скалярные типы являются POD типами), и в данном случае компилятор для представления нулевого указателя на член использует последовательность значений байт, отличную от последовательности нулей.
Во-вторых, зачем подобной языковой конструкции заполнять что-то нулевыми байтами, если это не обеспечивает как минимум валидность значения инициализируемого объекта? Раз ты сам взялся определять способ конструирования валидного дефолтного значения через добавление соответствующего пользовательского конструктора — тебе и карты в руки.
Re[11]: memset(this, 0, sizeof(T));
smeeld:
NI>>А что такое нулевое значение для класса "с виртуальной таблицей и прочими причиндалами"?
S>То же самое, что и для классов без причиндал, то есть, нулевое значение, заданных определением класса полей.
Значение объекта и последовательность значений байт в его представлении — это не одно и то же.
S>Если конструкция {} приравнивает нулю эти поля классов без причиндал, почему это не распространяется на иные классы?
Во-первых, нуль нулю рознь. Даже у объекта POD типа "нулевое" значение может быть представлено ненулевыми байтами, а последовательность из нулевых байт может образовывать ненулевое значение. Например:
Выхлоп:
http://coliru.stacked-crooked.com/a/e5cea54dc6d9dd14
int S::* — это скалярный тип (все скалярные типы являются POD типами), и в данном случае компилятор для представления нулевого указателя на член использует последовательность значений байт, отличную от последовательности нулей.
Во-вторых, зачем подобной языковой конструкции заполнять что-то нулевыми байтами или заниматься обнулением всех полей встроенных типов, если это не обеспечивает как минимум валидность значения инициализируемого объекта? Раз ты сам взялся определять способ конструирования валидного дефолтного значения через добавление соответствующего пользовательского конструктора — тебе и карты в руки.
NI>>А что такое нулевое значение для класса "с виртуальной таблицей и прочими причиндалами"?
S>То же самое, что и для классов без причиндал, то есть, нулевое значение, заданных определением класса полей.
Значение объекта и последовательность значений байт в его представлении — это не одно и то же.
S>Если конструкция {} приравнивает нулю эти поля классов без причиндал, почему это не распространяется на иные классы?
Во-первых, нуль нулю рознь. Даже у объекта POD типа "нулевое" значение может быть представлено ненулевыми байтами, а последовательность из нулевых байт может образовывать ненулевое значение. Например:
#include <cstring>
#include <iostream>
struct S
{
int i, j;
int S::*p;
};
#define PRINT_VALUE(expr) std::cout << #expr ": " << (expr) << std::endl;
int main()
{
S s;
s = S();
std::cout << std::boolalpha;
std::cout << "value-initialization" << std::endl;
PRINT_VALUE(s.p == nullptr);
PRINT_VALUE(s.p == &S::i);
PRINT_VALUE(s.p == &S::j);
std::memset(&s, 0, sizeof(s));
std::cout << "bytewise zeroing" << std::endl;
PRINT_VALUE(s.p == nullptr);
PRINT_VALUE(s.p == &S::i);
PRINT_VALUE(s.p == &S::j);
}Выхлоп:
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
value-initialization
s.p == nullptr: true
s.p == &S::i: false
s.p == &S::j: false
bytewise zeroing
s.p == nullptr: false
s.p == &S::i: true
s.p == &S::j: falsehttp://coliru.stacked-crooked.com/a/e5cea54dc6d9dd14
int S::* — это скалярный тип (все скалярные типы являются POD типами), и в данном случае компилятор для представления нулевого указателя на член использует последовательность значений байт, отличную от последовательности нулей.
Во-вторых, зачем подобной языковой конструкции заполнять что-то нулевыми байтами или заниматься обнулением всех полей встроенных типов, если это не обеспечивает как минимум валидность значения инициализируемого объекта? Раз ты сам взялся определять способ конструирования валидного дефолтного значения через добавление соответствующего пользовательского конструктора — тебе и карты в руки.