Передача умного указателя в качестве аргумента внутри класса: scoped_ptr или shared_ptr? - PullRequest
5 голосов
/ 17 марта 2009

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

class Foo {
   ...
};

class A {
   private:
      typedef scoped_ptr<Foo> FooPtr;

      void privateMethod1(FooPtr fooObj);

   public:
      void showSomethingOnTheScreen() {
          FooPtr fooObj(new Foo);
          privateMethod1(fooObj);
      };
};

Я считаю, что правильным интеллектуальным указателем в этом случае будет scoped_ptr, однако я не могу этого сделать, потому что scoped_ptr делает класс не подлежащим копированию при использовании таким образом, поэтому я должен сделать методы такими:

void privateMethod1(FooPtr& fooObj);

privateMethod1 не хранит объект и не хранит ссылки на него. Просто извлекает данные из класса Foo .

Возможно, правильным способом было бы вообще не использовать интеллектуальный указатель и не размещать объект в стеке, но это невозможно, потому что он использует библиотеку, которая не допускает объекты в стеке, они должны находиться в куче.

В конце концов, я все еще не уверен в реальном использовании scoped_ptr.

Ответы [ 5 ]

3 голосов
/ 17 марта 2009

Я бы использовал scoped_ptr внутри showSomethingOnTheScreen, но передал бы необработанный указатель (или ссылку) на privateMethod1, например

scoped_ptr fooObj (новый Foo);
privateMethod1 (fooObj.get ());

3 голосов
/ 17 марта 2009

Еще одна возможность - создать объект как static_ptr для простоты управления памятью, но просто передать необработанный указатель другим частным методам:

void privateMethod1(Foo *fooObj);

void showSomethingOnTheScreen() {
  scoped_ptr<Foo> fooObj(new Foo);
  privateMethod1(fooObj.get());
};
1 голос
/ 17 марта 2009

Я с подозрением отношусь к комментарию "он использует библиотеку, которая не позволяет объектам в стеке, они должны быть в куче".

Почему? Как правило, это означает, что они должны быть освобождены особым образом - поэтому, возможно, ни одно из этих решений не будет работать.

1 голос
/ 17 марта 2009

Используйте здесь простой std :: auto_ptr, поскольку вы не можете создавать объекты в стеке. И лучше вашей приватной функции просто принять необработанный указатель.

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

На самом деле, если ваш объект не изменяет объект, а ваш API возвращает объект наверняка, вам лучше использовать

void privateMethod1(const Foo& fooObj);

и передайте объект туда как

privateMethod1(*fooObj.get());
0 голосов
/ 17 марта 2009

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

class A {
   private:
      void privateMethod1(Foo& fooObj);

   public:
      void showSomethingOnTheScreen() {
          scoped_ptr<Foo> fooObj(new Foo);
          privateMethod1(*(fooObj.get()));
      };
};
...