Сообщение Re: Рекурсивные структуры данных и современный С++ от 01.02.2022 13:21
Изменено 01.02.2022 13:50 watchmaker
Re: Рекурсивные структуры данных и современный С++
Здравствуйте, cppguard, Вы писали:
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr)
Добавлять конструктор копирования для сложных структур данных — опасное решение из-за того, что можно легко и неявно просадить производительность.
Я не говорю, что это никогда не нужно. Но скорее стоит задуматься, а точно ли плюсы перевесят возможность ошибки.
C>Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок,
Гораздо важнее другое: теперь при копировании новые объекты будут ссылаться на общие узлы. Поменял содержимое в одном и оно поменяется в копии — совсем другая семантика.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал
У unique_ptr не просто так нет конструктора копирования. Но если нужно, то сделай свой умный указатель с копированием и используй его.
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr). Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок, время жизни объекта становится непонятным, ещё и барьеры синхронизации (а ведь нам говорили "you don't pay for what you don't use"). Как быть? Пример искусственный, можете представить любую рекурсивную структуру данных.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал, до код построения дерева мог бы быть таким:
Отличный пример, где отсуствие copy-конструктора помешало тебе совершить ошибку.
Это конечно не означает, что копирование не нужно. Скорее означает, что нужно понимать зачем оно нужно.
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr)
Добавлять конструктор копирования для сложных структур данных — опасное решение из-за того, что можно легко и неявно просадить производительность.
Я не говорю, что это никогда не нужно. Но скорее стоит задуматься, а точно ли плюсы перевесят возможность ошибки.
C>Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок,
Гораздо важнее другое: теперь при копировании новые объекты будут ссылаться на общие узлы. Поменял содержимое в одном и оно поменяется в копии — совсем другая семантика.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал
У unique_ptr не просто так нет конструктора копирования. Но если нужно, то сделай свой умный указатель с копированием и используй его.
условно так | |
| |
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>
C>struct trie {
C> std::unordered_map<char, unique_ptr<trie>> children;
C>};
C>
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr). Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок, время жизни объекта становится непонятным, ещё и барьеры синхронизации (а ведь нам говорили "you don't pay for what you don't use"). Как быть? Пример искусственный, можете представить любую рекурсивную структуру данных.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал, до код построения дерева мог бы быть таким:
Скрытый текст | |
C>
| |
Отличный пример, где отсуствие copy-конструктора помешало тебе совершить ошибку.
Это конечно не означает, что копирование не нужно. Скорее означает, что нужно понимать зачем оно нужно.
Re: Рекурсивные структуры данных и современный С++
Здравствуйте, cppguard, Вы писали:
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr)
Добавлять конструктор копирования для сложных структур данных — опасное решение из-за того, что можно легко и неявно просадить производительность.
Я не говорю, что это никогда не нужно. Но скорее стоит задуматься, а точно ли плюсы перевесят возможность ошибки.
C>Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок,
Гораздо важнее другое: теперь при копировании новые объекты будут ссылаться на общие узлы. Поменял содержимое в одном и оно поменяется в копии — совсем другая семантика.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал
У unique_ptr не просто так нет конструктора копирования. Но если нужно, то сделай свой умный указатель с копированием и используй его.
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr). Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок, время жизни объекта становится непонятным, ещё и барьеры синхронизации (а ведь нам говорили "you don't pay for what you don't use"). Как быть? Пример искусственный, можете представить любую рекурсивную структуру данных.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал, до код построения дерева мог бы быть таким:
Отличный пример, где отсуствие copy-конструктора помешало тебе совершить ошибку.
Это конечно не означает, что копирование не нужно. Скорее означает, что нужно понимать зачем оно нужно.
Грубо говоря, если владеющий указатель, а есть итератор. А ты пытаешься одним классом trie оба их реализовать..
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr)
Добавлять конструктор копирования для сложных структур данных — опасное решение из-за того, что можно легко и неявно просадить производительность.
Я не говорю, что это никогда не нужно. Но скорее стоит задуматься, а точно ли плюсы перевесят возможность ошибки.
C>Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок,
Гораздо важнее другое: теперь при копировании новые объекты будут ссылаться на общие узлы. Поменял содержимое в одном и оно поменяется в копии — совсем другая семантика.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал
У unique_ptr не просто так нет конструктора копирования. Но если нужно, то сделай свой умный указатель с копированием и используй его.
условно так | |
| |
C>Как их правильно готовить? Допустим, хотим реализовать trie в виде
C>
C>struct trie {
C> std::unordered_map<char, unique_ptr<trie>> children;
C>};
C>
C>но таким образом удаляется коструктор копирования по-умолчанию (из-за присутствия unique_ptr). Можно теперь заменить контейнер указателя на shared_ptr, но тогда все добавляется подсчёт ссылок, время жизни объекта становится непонятным, ещё и барьеры синхронизации (а ведь нам говорили "you don't pay for what you don't use"). Как быть? Пример искусственный, можете представить любую рекурсивную структуру данных.
C>Если бы, ну чисто теоретически, конструктор копирования по-умолчанию присутствовал, до код построения дерева мог бы быть таким:
Скрытый текст | |
C>
| |
Отличный пример, где отсуствие copy-конструктора помешало тебе совершить ошибку.
Это конечно не означает, что копирование не нужно. Скорее означает, что нужно понимать зачем оно нужно.
Грубо говоря, если владеющий указатель, а есть итератор. А ты пытаешься одним классом trie оба их реализовать..