Side effects when passing objects to function in C++

戏子无情 提交于 2019-12-01 06:02:55

That passage is probably talking about this situation:

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

Now A object is used as pass by value:

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
}

Here is an example:

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

    ~bad_design()
    {
        delete[] _buffer;
    }

private:
    char* _buffer;
};

Note that the class has a constructor and a destructor to handle the _buffer resource. It would also need a proper copy-constructor and assignment operator, but is such a bad design that it wasn't added. The compiler will fill those with the default implementation, that just copies the pointer _buffer.

When calling a function:

void f( bad_design havoc ){ ... }

the copy constructor of bad_design is invoked, which will create a new object pointing to the same buffer than the one passed as an argument. As the function returns, the local copy destructor will be invoked which will delete the resources pointed by the variable used as an argument. Note that the same thing happens when doing any copy construction:

bad_design first( 512 );
bad_design error( first );
bad_design error_as_well = first;

Here is another example. The point is that when the callee (SomeFunc) parameter destructor is invoked it will free the same object (ptr) pointed to by the caller argument (obj1). Consequently, any use of the caller argument (obj1) after the invocation will produce a segfault.

#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();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!