Вопрос

Допустим, у меня есть структура "s" с переменной-членом указателя int "i".Я выделяю память в куче для i в конструкторе s по умолчанию.Позже, в какой-то другой части кода, я передаю экземпляр s по значению некоторой функции.Я что, делаю здесь поверхностную копию?Предположим, я не реализовывал никаких конструкторов копирования, операторов присваивания или чего-либо еще для s...просто конструктор по умолчанию.

Это было полезно?

Решение

В продолжение того, что @[don.neufeld.myopenid.com] сказал: это не только мелкую копию, но это либо (выбрать) утечка памяти или оборванных указатель.

// memory leak (note that the pointer is never deleted)
class A
{
  B *_b;
  public:
  A()
  : _b(new B)
  {
  }
};

// dangling ptr (who deletes the instance?)
class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  {
    delete _b;
  }
};

Чтобы решить эту проблему, существует несколько методов.

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

class A
{
  B *_b;
  public:
  A()
  ... (same as above)

  ~A()
  ...

  A(const A &rhs)
  : _b(new B(rhs._b))
  {
  }

  A &operator=(const A &rhs)
  {
    B *b=new B(rhs._b);
    delete _b;
    _b=b;
    return *this;
};

Излишне говорить, что это серьезная проблема, и есть немало тонкостей, с которыми нужно разобраться.Я даже не совсем уверен, что сделал это прямо здесь, хотя делал это несколько раз.Не забывайте, что вам нужно скопировать всех участников - если позже вы добавите несколько новых, не забудьте добавить и их!

Сделайте конструктор копирования и operator= private в вашем классе. Это и есть решение "запереть дверь".Это просто и эффективно, но иногда чрезмерно защитно.

class A : public boost::noncopyable
{
  ...
};

Никогда не используйте необработанные указатели. Это просто и эффективно.Здесь есть много вариантов:

  • Используйте строковые классы вместо необработанных указателей на символы
  • Используйте std:: auto_ptr, boost:: shared_ptr, boost:: scoped_ptr и т. Д

Пример:

// uses shared_ptr - note that you don't need a copy constructor or op= - 
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
  boost::shared_ptr<B> _b;
  public:
  A()
  : _b(new B)
  {
  }
};

Другие советы

Да, это мелкая копия. Теперь у вас есть две копии s (одна в вызывающем, одна в стеке в качестве параметра), каждая из которых содержит указатель на тот же блок памяти.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top