ideas icon indicating copy to clipboard operation
ideas copied to clipboard

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

Open apolukhin opened this issue 4 years ago • 2 comments

Перенос предложения: голоса +2, -7 Автор идеи: ilnurkh

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

В более радикальной формулировке предлагается запретить создавать переменные и поля без начальных значений. Отказ от явной инициализации должен быть обозначен явным std::uninitialized

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

apolukhin avatar Mar 23 '21 16:03 apolukhin

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

В более радикальной формулировке предлагается запретить создавать переменные и поля без начальных значений. Отказ от явной инициализации должен быть обозначен явным std::uninitialized

yndx-antoshkka, 7 апреля 2017, 13:18 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() в контейнер нельзя - конструирование объектов должно происходить через allocator_traits<Allocator>::construct

Дальше надо исследовать и думать, как решать комплексно решить проблему.

ilnurkh, 7 апреля 2017, 13:28 yndx-antoshkka,

  1. не решит конечно, но можно делать ворнинг на отстутствие таких указаний (или аттрибутов).
  2. конечно это не законченное предложение а приглашение к обсуждению

yndx-antoshkka, 10 апреля 2017, 17:00 ilnur.khuziev, есть proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0632r0.html с идеей похожей на идею из пункт 1)

apolukhin avatar Mar 23 '21 16:03 apolukhin

В https://wg21.link/P2723 делают автоматическую инициализацию переменных, в рамках того же предложения хотят добавить механизм для явной инициализации мусором

apolukhin avatar Oct 23 '23 07:10 apolukhin