#c #pointers
#c #указатели
Вопрос:
У меня возникли некоторые проблемы с указателями. У меня есть класс
class Foo
{
private:
int var;
public:
Foo() = default;
void SetVar(int v) {var = v;}
};
на который мне нужно создать указатель в другом классе:
class Object
{
private:
Foo* ptr;
public:
Object() = default;
void func()
{
ptr->SetVar(10);
}
};
Это дает мне нарушение доступа на запись. Я думаю, что проблема связана с инициализацией ptr
, но я не знаю, как исправить эту проблему. Спасибо!
Комментарии:
1. Нет инициализации
Object::ptr
, и в этом проблема. Конструктор по умолчанию недостаточен, и предполагаетсяObject
, что предполагается сохранить право собственности наFoo
созданный вObject
конструкторе, деструктор также не справится с задачей…2. И не беспокойтесь о таких строках,
Foo() = defau<
пока не узнаете, зачем (в некоторых случаях) они нужны (опубликованный код этого не делает).3. Вы инициализировали
Foo
new
или адресомmember field
?4. Вам нужно будет создать объект
Foo
и указатьptr
на него. В зависимости от назначения кода это может быть сделано в разных местах, либо в конструктореObject
, либо внутриfunc
, либо из другой функции
Ответ №1:
Инициализируйте ptr
в constructor
Object
классе, и delete
это в destructor
! или использовать smart pointers
!
объявленный ptr
как
Foo* ptr = nullptr;
добавить определение для Object()
as
Object::Object()
{
ptr = new Foo();
}
и определение для ~Object()
as
Object::~Object()
{
if (ptr != nullptr)
{
delete ptr;
ptr = nullptr;
}
}
Комментарии:
1. Я бы предпочел не распределять переменные динамически. Есть ли какой-нибудь способ не делать этого?
2. Я изучал Windows API, где вы пишете такой код:
m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), amp;m_pBlackBrush);
есть ли способ реализовать этот метод, когда вы передаете ссылку в функцию, которая затем устанавливает ее равной экземпляру, в моем случае?3. @johndoe В этом коде нет ссылок (или где-либо в Windows API, основанном на C, который не имеет ссылок). Я думаю, вы неправильно
amp;
понимаете адрес оператора.4. @johndoe Но, конечно, вы можете написать код, подобный приведенному выше, на C , просто поймите, что он не использует ссылки.
5. Если бы я попытался сделать что-то подобное, как бы я сохранил объект от уничтожения?
Ответ №2:
Я думаю, что проблема связана с инициализацией ptr
Можно и так сказать. Вам не удалось инициализировать указатель перед косвенным обращением через указатель для доступа к объекту, на который не указывается.
Я не знаю, как исправить эту проблему.
Шаг 1: Создайте объект типа Foo
.
Шаг 2: Инициализируйте указатель адресом объекта, созданного на шаге 1.
Шаг 3 и далее: Убедитесь, что созданный объект остается в живых по крайней мере до тех пор, пока указатель.
Минимальный пример:
class Object
{
// ...
explicit Object(Foo* ptr): ptr(ptr) {}; // Step 2
// usage
Foo f; // Step 1
{
Object o{amp;f};
o.func();
} // step 3
Я рекомендую рассмотреть альтернативный дизайн, в котором вы сохраняете Foo
объект как объект-член, а не указываете на объект, хранящийся в другом месте.
Комментарии:
1. Возможно ли в этой ситуации использовать std::unique_ptr?
2. @johndoe Возможно, уре. Но зачем использовать динамическое распределение, если оно вам не нужно?