Побочные эффекты при передаче объектов в функцию в C ++ - PullRequest
5 голосов
/ 14 октября 2011

Я прочитал в C++ : The Complete Reference книгу следующее

Даже если объекты передаются в функции с помощью обычного механизм передачи параметров по значению, который теоретически защищает и изолирует вызывающий аргумент, это все еще возможно для стороны эффект, который может повлиять или даже повредить объект, используемый в качестве аргумент. Например, если объект, используемый в качестве аргумента, выделяет память и освобождает эту память, когда она уничтожается, затем ее локальная копия внутри функции освободит ту же память, когда ее деструктор называется. Это оставит исходный объект поврежденным и эффективно бесполезно.

Я не очень понимаю, как возникает побочный эффект. Может ли кто-нибудь помочь мне понять это на примере?

Ответы [ 3 ]

5 голосов
/ 14 октября 2011

Вот пример:

class bad_design
{
public:
    bad_design( std::size_t size )
      : _buffer( new char[ size ] )
    {}

    ~bad_design()
    {
        delete[] _buffer;
    }

private:
    char* _buffer;
};

Обратите внимание, что класс имеет конструктор и деструктор для обработки ресурса _buffer.Также потребуется правильный конструктор копирования и оператор присваивания, но такой плохой дизайн, что он не был добавлен.Компилятор заполнит те реализацией по умолчанию, которая просто копирует указатель _buffer.

При вызове функции:

void f( bad_design havoc ){ ... }

вызывается конструктор копирования bad_design, которыйсоздаст новый объект, указывающий на тот же буфер, чем тот, который передан в качестве аргумента.Когда функция вернется, будет вызван деструктор локального копирования, который будет delete ресурсами, указанными в переменной, используемой в качестве аргумента.Обратите внимание, что то же самое происходит при выполнении любой конструкции копирования:

bad_design first( 512 );
bad_design error( first );
bad_design error_as_well = first;
1 голос
/ 14 октября 2011

Этот отрывок, вероятно, говорит об этой ситуации:

class A {
  int *p;
public:
  A () : p(new int[100]) {}
  // default copy constructor and assignment
 ~A() { delete[] p; }
};

Теперь A объект используется как проход по значению:

void bar(A copy)
{
  // do something
  // copy.~A() called which deallocates copy.p
}
void foo ()
{
  A a;  // a.p is allocated
  bar(a);  // a.p was shallow copied and deallocated at the end of  'bar()'
  // again a.~A() is called and a.p is deallocated ... undefined behavior
}
0 голосов
/ 11 декабря 2014

Вот еще один пример. Дело в том, что когда вызывается деструктор параметра callee (SomeFunc), он освобождает тот же объект (ptr), на который указывает аргумент вызывающего (obj1). Следовательно, любое использование аргумента вызывающей стороны (obj1) после вызова приведет к возникновению ошибки.

#include <iostream>
using namespace std;

class Foo {
public:
    int *ptr;

    Foo (int i) {
        ptr = new int(i);
    }

    ~Foo() {
        cout << "Destructor called.\n" << endl;
        //delete ptr;
    }

    int PrintVal() {
        cout << *ptr;
        return *ptr;
    }
};

void SomeFunc(Foo obj2) {
    int x = obj2.PrintVal();
} // here obj2 destructor will be invoked and it will free the "ptr" pointer.

int main() {
    Foo obj1 = 15;

    SomeFunc(obj1);

    // at this point the "ptr" pointer is already gone.
    obj1.PrintVal();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...