Opened 4 years ago
Closed 4 years ago
#853 closed ожидаются исправления (задача сдана)
WW #12
Reported by: | Денис Лочмелис | Owned by: | Дмитрий Свиридкин |
---|---|---|---|
Component: | WW_vector | Version: | 2.0 |
Keywords: | Cc: |
Description
V1
Change History (3)
comment:1 Changed 4 years ago by
Owner: | changed from Дмитрий Свиридкин to Денис Лочмелис |
---|---|
Type: | ожидается проверка → ожидаются исправления |
comment:2 Changed 4 years ago by
Owner: | changed from Денис Лочмелис to Дмитрий Свиридкин |
---|---|
Version: | 1.0 → 2.0 |
Названия вернул, заголовок убрал.
Такой swap необходим для как раз следующей проблемы. Я думал-думал, так и не понял, что за проблема с временем жизни... Так что и это, и swap для rvalue пришлось оставить.
Убрал два noexcept. Починил resize.
Придумал способ тестирования на утечки: рандомно кидать исключение в конструкторе Product'а. Потратил 2 часа на то, чтобы понять, что такой объект сам базовую гарантию не выполняет и в утечках вектор не виноват. От этого осталась закомменченная функция.
comment:3 Changed 4 years ago by
Resolution: | → задача сдана |
---|---|
Status: | assigned → closed |
include/my_vector.h:56:6: error: ‘ostream’ in namespace ‘std’ does not name a type 56 | std::ostream& operator<<(std::ostream& ostr, const my_vector<T>& vec) noexcept; | ^~~~~~~ include/my_vector.h:5:1: note: ‘std::ostream’ is defined in header ‘<ostream>’; did you forget to ‘#include <ostream>’? 4 | #include <cstddef> +++ |+#include <ostream>
rc/main.cpp:21:15: error: ‘my_vector’ does not name a type; did you mean ‘my_vector_nsp’? 21 | using myvec = my_vector::my_vector<T>;
Не надо придумывать себе проблемы и героически их превозмогать, создавая неестественные методы. получать ссылку на поле временного объекта -- код содержащий потенциальные ошибки.
Поэтому такую ерунду:
impl.swap(my_vector(other).impl);
Нужно переписать как
my_vector tmp(other); impl.swap(tmp.impl);
include/my_vector_impl.h:156:33: note: initializing argument 1 of ‘void my_vector::my_vector<T>::push_back(T&) [with T = MinimalClass]’ 156 | void my_vector<T>::push_back(T& t) { | ~~~^ src/main.cpp: In instantiation of ‘void push_vector(myvec<T>&, std::size_t) [with T = int; myvec<T> = my_vector::my_vector<int>; std::size_t = long unsigned int]’: src/main.cpp:275:16: required from ‘void test_pop_and_push_back() [with T = int]’ src/main.cpp:849:37: required from here src/main.cpp:201:36: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’ 201 | vec.push_back(get_object<T>(i));
push_back нарушает строгую гарантию -- вы сделали реаллокацию, а потом полетело исключение.
my_vector buf; buf.reserve(n); reserve(n); for (; buf.impl.size < impl.size; buf.impl.size++) { buf.impl.data[buf.impl.size] = impl.data[buf.impl.size]; } for (; buf.impl.size < n; buf.impl.size++) { new (buf.impl.data + buf.impl.size) T(); // noexcept = false } impl.swap(buf.impl);
- Тут UB. Нельзя использовать оператор присваивания к несозданному объекту.
- зачем нужен reserve над текущим вектором, если вы его никак не используете, а потом делаете swap?
6.5
Менять публичные интерфейсы (даже если в них такая оказия случилась) просто так нельзя
в *_impl.h не надо подключать исходный заголовок
Своп с такой сигнатурой обычно не делают. Потому что это move-присваивание, а не swap. И для реализации такого присваивания достаточно swap для lvalue.
impl.swap(my_vector(other).impl);
Тут точно все в порядке с временем жизни? Ради экономии одной строки рисковать наиграть UB при смене стандарта на более ранний?noexceptы там, где их быть не должно, приводят к UB. Ищите.
resize нарушает строгую гарантию исключений.