Явная инициализация мусором

ilnur.khuziev
ilnur.khuziev

Обращаю внимание, что нельзя просто писать std::vector vector_with_trash(100, std::uninitialized<int>()); потому что такой код должен создать вектор со 100 одинаковыми значениями (пусть и мусорными).

-5
рейтинг
4 комментария
ilnur.khuziev
дублирую описание:
Возможность не задавать инициализирующий значения является постоянным источником ошибок. Более того, в ряде случаев не возможность явного указания отсутствия начального значения является причиной ненужных действий (например при необходимости создать std::vector с заданным количеством элементов а затем перезаписать все его значения).
Предлагаю для начала разрешить код вида: int var = std::uninitialized(); .
А также дать возможность писать подобное std::vector vector_with_trash(100, std::unitialized_constructor);

В более радикальной формулировке предлагается запретить создавать переменные и поля без начальных значений. Отказ от явной инициализации должен быть обозначен явным std::uninitialized
ilnur.khuziev
yndx-antoshkka
ilnur.khuziev, int var = std::uninitialized(); не решит проблемы - пользователи будут так писать и будут так же забывать проинициализировать переменные. Проблему пока что лучше всего решают -Wall -Werror которые врубают статический анализ кода и находят места где переменные могут быть не проинициализированы.

Решать проблему с отсутсвием неинициализирующих конструкторов надо сразу для всех контейнеров. У большинства sequence контейнеров есть констуркторы и resize которые принимают только размер, и соответственно будет вызываться std::allocator.construct(pointer) без параметров для инициализации. К сожалению allocator<T>.construct(pointer) вызывает new(pointer) T(); а это проинициализирует T нулём (если T - численный тип). Если подсунуть свой особый аллокатор, то можно избежать инициализации:

template <class T>
struct my_allocator: public std::allocator<T> {
using value_type = typename std::allocator<T>::value_type;

template<class Other>
struct rebind { typedef my_allocator<Other> other; };

template< class U>
void construct(U* p) {
::new (static_cast<void*>(p)) T;
}
};

Только вот контейнер с таким аллокатором нельзя переместить в контейнер с обычным аллокатором.

Просто передать std::uninitialized<int>() в контейнер нельзя - конструирование объектов должно происходить через allocator_traits<Allocator>::construct

Дальше надо исследовать и думать, как решать комплексно решить проблему.
yndx-antoshkka
ilnur.khuziev
yndx-antoshkka,
1) не решит конечно, но можно делать ворнинг на отстутствие таких указаний (или аттрибутов).
2) конечно это не законченное предложение а приглашение к обсуждению
ilnur.khuziev
yndx-antoshkka
ilnur.khuziev, есть proposal open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0632r0.html с идеей похожей на идею из пункт 1)
yndx-antoshkka
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).