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) を使用すると、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();
}
于 2014-12-11T16:56:05.920 に答える