5

我在书中读过C++ : The Complete Reference以下内容

即使对象是通过正常的按值调用参数传递机制传递给函数的,理论上这种机制可以保护和隔离调用参数,但仍有可能发生可能影响甚至损坏的副作用, 用作参数的对象。例如,如果用作参数的对象分配内存并在销毁时释放该内存,则函数内部的本地副本将在调用其析构函数时释放相同的内存。这将使原始对象损坏并且实际上无用。

我真的不明白副作用是如何发生的。任何人都可以通过一个例子帮助我理解这一点吗?

4

3 回答 3

5

这是一个例子:

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;
于 2011-10-14T04:25:57.917 回答
1

那段话大概就是在讲这种情况:

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
}
于 2011-10-14T04:24:36.457 回答
0

这是另一个例子。关键是,当调用被调用者 (SomeFunc) 参数析构函数时,它将释放调用者参数 (obj1) 指向的同一对象 (ptr)。因此,调用后调用者参数 (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();
}
于 2014-12-11T16:56:05.920 回答