Opened 4 years ago

Closed 4 years ago

#838 closed ожидается проверка (задача сдана)

WW #12

Reported by: Ruslan Salkaev Owned by: Sokolov Viacheslav
Component: WW_vector Version:
Keywords: Cc:

Description


Change History (5)

comment:1 Changed 4 years ago by Sokolov Viacheslav

Type: ожидается проверкаожидаются исправления

Не выполнено требование

Новое требование: всё, кроме main, должно лежать в каком-нибудь пространстве имён; обязательно использовать анонимные пространства имён, где разумно.

37 const T &operator[](std::size_t index);

У std::vector две перегрузки, Вам тоже нужны их реализовать.

11 try{
12 array_ = reallocate_array(1);
13 } catch(...) {
14 throw;
15 }

какая мотивация делать такой try..catch?

Кроме того, не проще ли поддержать в общем коде

19 my_vector::my_vector<T>::my_vector(std::size_t n):size_(n) {

случай n = 0?

60 size_t count_capacity(size_t start_cap, size_t required) const noexcept;

имя метода не самое удачное. Можно пометить static.
Предлагаю именовать в духе raise_capacity_to_hold

58 T * reallocate_array(size_t n);

static?
почему reallocate, если перевыделения не происходит?

50 array_ = std::move(other.array_);

здесь move не по делу, для указателей он ничего не делает

88 T *tmp = other.array_;
189 other.array_ = array_;
190 array_ = tmp;
191 tmp = nullptr;
std::swap(array_, other.array_)?

196 template<typename T>
197 void my_vector::my_vector<T>::free_array(size_t n) noexcept {
198 for (; n > 0; --n) {
199 array_[n - 1].~T();
200 }
201 }
с таким интерфейсом можно ошибиться и часть деструкторов не позовется. Лучше поддерживать size_ в актуальном состоянии в конструкторах, а из этого метода убрать аргумент n.

92 return !size_;

читаемее 0 == size_

107 } catch (...) {
108 throw;
109 }
эквивалентно тому, чтобы не делать try..catch

103 while (size_ < n) {
104 new(array_ + size_)T();
105 ++size_;
106 }
с такой реализацией нарушется требование строгой гарантии исключений (если исключение произойдет в очередном T{} - например, out_of_memory). Для реализации этой гарантии нужен временный объект.

114 if (n < capacity_)
115 return;
<=

121 for (i = 0; i < size_; ++i) {
122 new(new_array + i) T(std::move(array_[i]));
123 }
124 free_array(size_);
125 std::free(array_);
126 array_ = new_array;
127 capacity_ = new_cap;
лучше вынести эту часть из-под try..catch, потому что она noexcept.

129 free_array(i);
это корректно только потому, что в этом случае i = 0

137 if (index >= size_)
138 throw;

throw;

Rethrows the currently handled exception ... This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise).

https://en.cppreference.com/w/cpp/language/throw

159 array_[size_].~T();
почему так?

181 os << array_[i] << " ";
в условии просят не выводить последний пробел

free_array не освобождает память. Предлагаю переименовать в destruct или что-то вроде того.

В тестах const-версии методов не протестированы. Также не протестировано конструкция вида a[i] = 1;.

Если я правильно понимаю, то задача была сдана перед deadline-ом, соответственно версия 2 - финальная. Поправьте, если ошибаюсь.

comment:2 Changed 4 years ago by Ruslan Salkaev

Type: ожидаются исправленияожидается проверка

comment:3 Changed 4 years ago by Sokolov Viacheslav

include/my_vector_test.h: In instantiation of ‘void test::my_vector_test<T>::test_operator_at() [with T = int]’:
include/my_vector_test.h:26:13: required from ‘void test::my_vector_test<T>::run_tests() [with T = int]’
src/main.cpp:65:21: required from here
include/my_vector_test.h:147:15: error: catching polymorphic type ‘class std::range_error’ by value [-Werror=catch-value=]

147 | } catch (std::range_error) {

|

include/my_vector_test.h: In instantiation of ‘void test::my_vector_test<T>::test_pop_back() [with T = int]’:
include/my_vector_test.h:29:13: required from ‘void test::my_vector_test<T>::run_tests() [with T = int]’
src/main.cpp:65:21: required from here
include/my_vector_test.h:192:15: error: catching polymorphic type ‘class std::logic_error’ by value [-Werror=catch-value=]

192 | } catch (std::logic_error) {

|

include/my_vector_test.h: In instantiation of ‘void test::my_vector_test<T>::test_operator_at_assign() [with T = int]’:
include/my_vector_test.h:37:13: required from ‘void test::my_vector_test<T>::run_default_constructible_tests() [with T = int]’
src/main.cpp:66:43: required from here
include/my_vector_test.h:165:15: error: catching polymorphic type ‘class std::range_error’ by value [-Werror=catch-value=]

165 | } catch (std::range_error) {

|

include/my_vector_test.h: In instantiation of ‘void test::my_vector_test<T>::test_operator_at() [with T = product::Product]’:
include/my_vector_test.h:26:13: required from ‘void test::my_vector_test<T>::run_tests() [with T = product::Product]’
src/main.cpp:67:21: required from here
include/my_vector_test.h:147:15: error: catching polymorphic type ‘class std::range_error’ by value [-Werror=catch-value=]

147 | } catch (std::range_error) {

|

include/my_vector_test.h: In instantiation of ‘void test::my_vector_test<T>::test_pop_back() [with T = product::Product]’:
include/my_vector_test.h:29:13: required from ‘void test::my_vector_test<T>::run_tests() [with T = product::Product]’
src/main.cpp:67:21: required from here
include/my_vector_test.h:192:15: error: catching polymorphic type ‘class std::logic_error’ by value [-Werror=catch-value=]

192 | } catch (std::logic_error) {

comment:4 Changed 4 years ago by Ruslan Salkaev

Исправил

comment:5 Changed 4 years ago by Sokolov Viacheslav

Resolution: задача сдана
Status: assignedclosed

const-версии методов так и остались непротестированными.

24 my_vector<T> tmp = allocate_vector(other.capacity_);
25 for (size_t i = 0; i < other.size_; i++) {
26 tmp.push_back(other[i]);
27 }
28 *this = std::move(tmp);

С делегирующим конструктором есть особенность. После его завершения объект считается сконструированным, соответствтенно если здесь вылетит исключение - позовется деструктор. Поэтому на самом деле временный объект не нужен.

31 template<typename T>
32 my_vector<T>::my_vector(my_vector <T> &&other) noexcept :size_(other.size_), capacity_(other.capacity_),
33 array_(other.array_) {
34 other.array_ = nullptr;
35 other.capacity_ = 0;
36 other.size_ = 0;
37 }
38

проще было бы через default-ctor + swap

103 for (std::size_t i = size_; i < n; ++i) {
104 tmp[i].~T();
105 }
здесь будет обращение к неинициализированной памяти через tmp[i]. Верхняя граница должна быть не n, а сколько удалось к этому моменту сконструировать.
Кроме того, у tmp size == 0, поэтому здесь вылетит исключение при обращении.

158 for (std::size_t i = 0; i < v.size() - 1; i++) {
если v.size() == 0, здесь будет длиииннный цикл

170 result.array_ = reinterpret_cast<T *>(new char[sizeof(T) * capacity]);
здесь хорошо бы проверить, что произведение не переполняется (т.е. что не просят слишком много capacity)

189 size_t ceil_power_of_two(size_t n) noexcept {
190 std::size_t result = 1;
191 while (result < n)
192 result *= 2;
193 return result;
194 }
при большом n это зациклится

91 for (std::size_t i = size_ - 1; i >= n; --i) {
зациклится, если n = 0

Note: See TracTickets for help on using tickets.