在c++中,不允许将对象直接传递给函数
In C++, is not permitted to pass an object to function directly?
我懂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.p
和o.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
的副本,并且它的成员指向与原始对象相同的位置,因为您没有声明复制构造函数。副本被销毁,内存被删除。原对象已损坏
- 如何使用单独文件中的派生类访问友元函数对象
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 有没有办法将重载的类函数绑定到函数对象?
- 将指针传递到成员的指针,从模板参数包到函数对象
- 如何在类模板的成员函数中正确调用函数对象?正在生成 Visual Studio 编译器错误 C2440
- 隐式转换为比较函数对象(函子)用于 std::sort 而不是 std::map?
- C++使用函数对象的线程,如何调用多个析构函数而不是构造函数?
- 如何通过接口将函子分配给函数对象
- 对std::函数对象的调用不匹配,该对象是指向成员函数的指针
- 指向std::invoke中成员函数对象的指针
- 如何成功地将函数对象(或lambda)传递给trackbar回调的第二个参数(void*)
- "std::function"的简单版本:函数对象的生存期?
- C++ 将函数对象作为左值和/或右值传递
- SFINAE 用于具有默认参数的函数对象
- 构造函数对象赋值是否泄漏内存
- 如何发送通过绑定到函数/方法创建的函数对象?
- std::for_each 与函数对象
- 将函数对象传递给 std::function
- 访问执行策略for_each函数对象中的迭代器
- 通过C++函数对象类访问参数