我已在C++ : The Complete Reference
中读到以下内容
即使通过法线将对象传递给函数 call-by-value参数传递机制,理论上可以保护 并且使调用参数绝缘,对于一方来说仍然是可能的 可能影响甚至损坏用作物体的物体 论点。例如,如果用作参数的对象分配 内存并在销毁时释放内存,然后释放其本地副本 函数内部将在其析构函数时释放相同的内存 调用。这将使原始对象受损且有效 无用的。
我真的不明白副作用是如何发生的。有人可以通过一个例子来帮助我理解这个吗?
答案 0 :(得分: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;
答案 1 :(得分: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
}
答案 2 :(得分:0)
这是另一个例子。关键是当调用callee(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();
}