Как преобразовать локальную переменную в указатель в C ++? - PullRequest
5 голосов
/ 01 ноября 2010

У меня есть переменная, которая является объектом:

Foo x;

И мне нужно вызвать функцию, которая требует Foo *. Как я могу конвертировать из Foo в Foo *.

Я знаю, что это не сработает:

Foo* y = &x;
o->setFoo(y);

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

Как я могу это сделать?

Примечание: Я не могу изменить функцию или тип переменной a!

Ответы [ 4 ]

6 голосов
/ 01 ноября 2010

Если определен соответствующий конструктор копирования,

o->setFoo(new Foo(x));

Но тогда деструктор o должен удалить xsetFoo, вероятно, тоже должен, если он установлен. \ S уже установлен).

Примечание: определения деструктора недостаточно.
Конструктор копирования / оператор присваивания также должны быть определены и:

  • Должен быть отключен
  • или понять, на что они указывают, и выполнить глубокое копирование
  • или понять общее владение и отследить, сколько владельцев имеет указатель.

См. Правило 4 для объяснения.

Если вы вообще не можете коснуться определения класса o, то вам нужно быть очень осторожным с распределением / освобождением памяти, чтобы не допустить утечки памяти.

2 голосов
/ 01 ноября 2010

Чтобы дать наиболее точный ответ на этот вопрос, необходимо предоставить информацию о том, должен ли o управлять жизненным циклом предоставленного Foo, и, если нет, жизненным циклом o.

Во-первых, это может работать нормально, это зависит от того, что o будет делать с предоставленным Foo.

Я знаю, что это не сработает:

Foo* y = &x;
o->setFoo(y);

Поскольку «x» - локальная переменная, поэтому она будет уничтожена, а указанный мною указатель не будет указывать на ничто.

Хорошо, допустим, что o имеет тип Bar

1 Бар управляет Foo - т.е.удалит Foo.

Панель будет уничтожена, при этом она должна сделать что-то, чтобы удалить Foo. В зависимости от того, что вам нужно сделать с Foo, чтобы настроить его, вы можете перейти к простому

{
 std::auto_ptr<Bar> o = new Bar();
 o->setFoo(new Foo());
 o->DoStuff();
}

или чуть более сложный

{
 std::auto_ptr<Foo> y = new Foo(...);
 y->config();
 o->setFoo(y.release());
}

2 Бар не управляет Foo - т.е.попробуйте удалить Foo

Если Bar не управляет Foo, то это ваша работа, но вполне вероятно, что Bar должен быть уничтожен до того, как Foo

2.1 позволит предположить, что Bar используется только втекущая область действия
Здесь Bar будет уничтожен до того, как Foo

{
 Foo y;
 std::auto_ptr<Bar> o = new Bar();
 o->setFoo(&y);
 o->DoStuff();
}

2.2 позволит предположить, что Bar используется только во внутренней области видимости

SomeFunc( Foo *y );
{
 std::auto_ptr<Bar> o = new Bar();
 o->setFoo(y);
 o->DoStuff();
}

{
 Foo y;
 SomeFunc( &y );
}

2.3 позволяет предположить, что у вас есть Bar, который будетиспользуется в различных областях

std::auto_ptr<Foo> y = new Foo();
std::auto_ptr<Bar> o = new Bar();

{
 o->setFoo(y.get());
}
{
 o->DoStuff();
}

, а затем могут быть предоставлены дополнительные примеры, основанные на том, как вы работаете с Foo для нескольких баров, включая контейнеры и т. д.

2 голосов
/ 01 ноября 2010

Вы должны выделить в куче ключевое слово new:

Foo* y = new Foo;
o->setFoo(y);

, хотя позднее вам придется управлять удалением Foo, иначе вы получите утечку памяти.

1 голос
/ 01 ноября 2010

Вы можете выделить объект класса Foo динамически, используя new, например,

o->setFoo(new Foo);

Обратите внимание, что вы должны принять во внимание владение этим объектом, потому что если setFoo не удалит его, у вас будет утечка памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...