#c #unique-ptr #delete-operator #rvalue-reference #template-classes
#c #уникальный-ptr #удалить-оператор #rvalue-ссылка #шаблоны-классы #c #оператор удаления #классы шаблонов
Вопрос:
Я пытаюсь понять, как уникальные указатели перемещают семантику. Теперь я создал фиктивный пример ниже, чтобы показать, в чем проблема. Мой вопрос в том, почему этот код выдает ошибку «освобождаемый указатель не был выделен»?:
#include <iostream>
#include <memory>
using namespace std;
template <class T>
class Object
{
public:
T *values = nullptr;
int size;
Object(int size) : size(size)
{
values = new T[size];
}
~Object()
{
delete[] this->values;
}
void myFunc(T *amp;amp;new_values)
{
cout << "myFunc called!" << endl;
delete[] this->values;
values = new_values;
}
void print()
{
for (int i = 0; i < size; i )
cout << this->values[i] << " ";
cout << endl;
}
};
int main()
{
auto my_object = new Object<int>(4);
std::unique_ptr<Object<int>> my_other_object(new Object<int>(4));
int values[4] = {1, 2, 3, 4};
int my_other_values[4] = {10, 20, 30, 40};
/* This works all fine! */
my_object->myFunc(std::move(values));
my_object->print();
/* This next bit throws pointer being freed was not allocated */
my_other_object->myFunc(std::move(my_other_values));
my_other_object->print();
}
Комментарии:
1. Вы не можете переместить массив, выделенный в стеке, в свой «уникальный ptr», потому что удалить[] этот массив — это UB, он никогда не был обновлен. Фактически это похоже на выполнение:
int x = 4; { auto p = std::unique_ptr<int>(amp;x); }
, что тоже не является законным.2. Ах, теперь в этом так много смысла. Спасибо, сэр!
Ответ №1:
Это не имеет никакого отношения к std::unique_ptr
. Причина, по которой вы получаете ошибку «освобождаемый указатель не был выделен», заключается в том, что показанный код пытается сделать delete
то, чего не было newed
.
delete[] this->values;
values = new_values;
Это правильно delete
старое values
, но затем просто слепо устанавливает values
, чтобы указать на то, что никогда не было new
отредактировано (те new_values
, которые передаются здесь, нигде не new
редактируются).
Следовательно, позже деструктор этого объекта попытается сделать delete
то, что сейчас находится в values
, но он никогда не был new
отредактирован (он просто указывает на некоторый статический массив), и вы получите ошибку времени выполнения.