在c++中,不允许将对象直接传递给函数

In C++, is not permitted to pass an object to function directly?

本文关键字:函数 对象 c++ 不允许      更新时间:2023-10-16

我懂C,但不擅长c++。

下面的代码将崩溃(在getval()中,使用reference作为参数是可以的)。*p的值在第一次cout语句后改变。

我的问题是为什么它崩溃了(或者为什么它的值改变了)。它是"按值调用"的对象,所以它应该工作吗?

class myclass { 
  int *p; 
  public: 
    myclass(int i); 
    ~myclass() { delete p; } 
    int getval(myclass o); 
}; 
myclass::myclass(int i) 
{ 
  p = new int; 
  if (!p) { 
    cout << "Allocation errorn"; 
    exit(1); 
  } 
  *p = i; 
}
int myclass::getval(myclass o) 
{ 
  return *o.p; 
} 
int main() 
{ 
  myclass a(1), b(2); 
  cout << a.getval(a) << " " << a.getval(b) << endl; 
  cout << b.getval(a) << " " << b.getval(b) << endl; 
  return 0; 
} 

阅读三个规则

本质上,你的代码不支持按值复制。

动态分配的内存被提前释放(由析构函数)。

干杯,hth。

我的问题是为什么它崩溃了(或者为什么它的值被改变了)。

这是浅复制和双删除非常常见的问题。编译器选择默认的复制构造函数,a.po.p都指向相同的内存位置。当两个对象都调用它们的析构函数时,delete p;语句被执行两次。多次释放相同的内存是未定义的行为,它会导致系统崩溃。

它是对象的"按值调用",所以它应该工作吗?

如果正确编码,那么yes它将工作。对p的内容进行深度复制,然后它应该可以工作。然而,最好是通过引用传递,直到它是可能的。

就c++语言而言,您所做的是允许的。但这是非常非常糟糕的编程。它不想在你的每一行代码上都加注释。相反,我重写了整个代码,您将此代码与您的代码进行比较,并查看代码中嵌入的注释:

class myclass { 
  int p;  //no pointer, as it is not needed
  public: 
    myclass(int i) : p(i) {} //use member initialization-list 
    int getval() const  //no parameter, and make the function const
    {
         return p;
    }
}; 
int main() 
{ 
  myclass a(1), b(2); 
  cout << a.getval() << endl;
  cout << b.getval() << endl; 
  return 0; 
} 

您正在传递myclass作为值,因此创建copy。当myclass::getval返回时,堆栈被展开,myclass析构函数被调用,释放指针指向另一个对象的内存。

你在这里双重删除p,共享指针可能是有用的,如果你不想做一个深度复制。只要有可能并且有意义,尝试使用自动变量来代替(用int代替int*)

您还没有实现复制构造函数(如果实现了,请记住三原则),因此当副本被销毁时,您将多次释放相同的内存。

提示:

实现复制构造函数:

myclass(const myclass& other)
{
   p = new int;
   *p = *other.p;
}

通过引用传递:

int getval(const myclass& o); 

一个好的规则是使函数不依赖于对象本身是静态的(这在这种特殊情况下没有帮助,但仍然有用)。由于getval不访问任何对象成员,因此可以将其设置为静态。

崩溃原因:

当调用getval(o)时,创建了o的副本,并且它的成员指向与原始对象相同的位置,因为您没有声明复制构造函数。副本被销毁,内存被删除。原对象已损坏