在函数内部new一个对象,return之后怎么delete?求大神解答

uangyy 2015-04-21 11:23:12
[b]class A
{
public:
A return_A()
{
A *a = new A();
return *a;
}
};

int main(void)
{
A a1;
A a2;
a2 = a1.return_A();
return 0;
}

请问在A的函数中new了一个新的对象,但是返回的是对象不是指针。那么函数体中的对象怎么delete,只能通过指针返回之后再delete吗?
...全文
2092 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
wy_ei 2015-04-23
  • 打赏
  • 举报
回复
这里可以使用智能指针,在函数作用域结束后智能指针会调用自己的析构函数,在析构函数里面会自动释放指向的内存。
sumos 2015-04-23
  • 打赏
  • 举报
回复
果断 std::shared_ptr<A> ReturnA() { std::shared_ptr<A> p = std::make_shared<A>(); ... return p; }
mewiteor 2015-04-22
  • 打赏
  • 举报
回复
可以
A& return_A()
{
     A *a = new A();
     return *a;
}
然后
A& a2=a1.return_A();
之后
delete &a2;
不过在return_A里最好用安全指针,比如
unique_ptr<A> a(new A());
return *a;
然后就不用手动delete了。
william7_138 2015-04-22
  • 打赏
  • 举报
回复
引用 1 楼 mewiteor 的回复:
可以
A& return_A()
{
     A *a = new A();
     return *a;
}
然后
A& a2=a1.return_A();
之后
delete &a2;
不过在return_A里最好用安全指针,比如
unique_ptr<A> a(new A());
return *a;
然后就不用手动delete了。
这里和这位同学有点不同意见,我觉得即便返回的是引用,其实在return的时候是以bitwise的方式把*a的内容拷贝给了a2,函数返回之后a2仍然无法操作在函数return_A中申请的堆内存,因此还是会有内存泄漏。 建议楼主以后遇到堆内存,还是使用指针操作。
12304108 2015-04-22
  • 打赏
  • 举报
回复
new出来的对象,最好是用指针操作,返回出去的也应该是指针,不然没法释放了。
william7_138 2015-04-22
  • 打赏
  • 举报
回复
引用 9 楼 mewiteor 的回复:
[quote=引用 8 楼 william7_138 的回复:] [quote=引用 1 楼 mewiteor 的回复:] 可以
A& return_A()
{
     A *a = new A();
     return *a;
}
然后
A& a2=a1.return_A();
之后
delete &a2;
不过在return_A里最好用安全指针,比如
unique_ptr<A> a(new A());
return *a;
然后就不用手动delete了。
这里和这位同学有点不同意见,我觉得即便返回的是引用,其实在return的时候是以bitwise的方式把*a的内容拷贝给了a2,函数返回之后a2仍然无法操作在函数return_A中申请的堆内存,因此还是会有内存泄漏。 建议楼主以后遇到堆内存,还是使用指针操作。[/quote] 实测不会调用拷贝构造函数。
#include<iostream>
#include<iomanip>
using namespace std;
class A
{
	private:
		const char* _s;
	public :
		A(const char* s):_s(s)
		{
			cout<<"constructor:";
			if(s)
				cout<<s;
			cout<<endl;
		}
		A(const A& a)
		{
			_s=a._s;
			cout<<"copy constructor:";
			if(_s)
				cout<<_s;
			cout<<endl;
		}
		A(A&& a)
		{
			_s=a._s;
			a._s=nullptr;
			cout<<"move constructor:";
			if(_s)
				cout<<_s;
			cout<<endl;
		}
		~A()
		{
			cout<<"destructor:";
			if(_s)
			{
				cout<<_s;
				_s=nullptr;
			}
			cout<<endl;
		}
		A& return_A(const char*s)
		{
			cout<<"return_A start"<<endl;
			A* a=new A(s);
			cout<<"return_A end"<<endl;
			return *a;
		}
		const char *getString()
		{
			return _s;
		}
};
int main()
{
	cout<<"start"<<endl;
	A a1("a1");
	cout<<"call return_A start"<<endl;
	A& a2=a1.return_A("a1->a2");
	cout<<"call return_A end"<<endl;
	cout<<"a2._s("<<setbase(ios::hex)<<setw(sizeof(size_t)*2)<<setfill('0')
		<<(size_t)a2.getString()<<") == "<<(a2.getString()?a2.getString():"nullptr")<<endl;
	delete &a2;
	cout<<"a2._s("<<setbase(ios::hex)<<setw(sizeof(size_t)*2)<<setfill('0')
		<<(size_t)a2.getString()<<") == "<<(a2.getString()?a2.getString():"nullptr")<<endl;
	cout<<"end"<<endl;
	return 0;
}
/*
output:
start
constructor:a1
call return_A start
return_A start
constructor:a1->a2
return_A end
call return_A end
a2._s(17232304) == a1->a2
destructor:a1->a2
a2._s(00000000) == nullptr
end
destructor:a1
*/
因为成员函数返回的是引用,定义的a2也是引用类型,所以不会产生新的对象。[/quote] 刚才引用错了··· 不好意思,早上有事情,所以这个帖子看的比较匆忙,我当时只是复制了LZ的的代码在调试,然后看到你写的第一个把函数的返回值改成引用类型,没看到把a2也改成了引用,所以出了点误会,不好意思,这位同学。我刚才试了一下,引用是可以的,而且我也对比了引用和指针两种实现的反汇编,发现也是基本一致的,这说明使用你说的引用也可以达到释放内存的目的。
william7_138 2015-04-22
  • 打赏
  • 举报
回复
引用 8 楼 william7_138 的回复:
[quote=引用 1 楼 mewiteor 的回复:] 可以
A& return_A()
{
     A *a = new A();
     return *a;
}
然后
A& a2=a1.return_A();
之后
delete &a2;
不过在return_A里最好用安全指针,比如
unique_ptr<A> a(new A());
return *a;
然后就不用手动delete了。
这里和这位同学有点不同意见,我觉得即便返回的是引用,其实在return的时候是以bitwise的方式把*a的内容拷贝给了a2,函数返回之后a2仍然无法操作在函数return_A中申请的堆内存,因此还是会有内存泄漏。 建议楼主以后遇到堆内存,还是使用指针操作。[/quote] 不好意思,早上有事情,所以这个帖子看的比较匆忙,我当时只是调试了LZ的的代码在调试,然后看到你写的第一个把函数的返回值改成引用类型,没看到把a2也改成了引用,所以出了点误会,不好意思,这位同学。我刚才试了一下,引用是可以的,而且我也对比了引用和指针两种实现的反汇编,发现也是基本一致的,这说明使用你说的引用也可以达到释放内存的目的。
uangyy 2015-04-22
  • 打赏
  • 举报
回复
引用 5 楼 zmlovelx 的回复:
妖怪放出来后,抓到必须收起来。
不知道怎么抓。。知道栈对象在函数结束的时候回自动调用析构函数,但是堆对象return之后就没法delete了,所以不是很理解
帅得不敢出门 2015-04-22
  • 打赏
  • 举报
回复
妖怪放出来后,抓到必须收起来。
xiaohuh421 2015-04-22
  • 打赏
  • 举报
回复
既然你要返回对象, 就完全可以不用new class A { public: A return_A() { A a return a;//返回对象, 会被复制, 不用担心返回的是栈变量 } }; 用了new, 那么你就得返回指针, 否则就漏了.
ysnis 2015-04-22
  • 打赏
  • 举报
回复
A* return_A()
wwwboyxa 2015-04-22
  • 打赏
  • 举报
回复
这就典型的内存泄漏,程序或函数结束了,你申请的内存没有指针再指向。
花山主人 2015-04-22
  • 打赏
  • 举报
回复
引用 10 楼 bear234 的回复:
你都new了,为什么不返回指针?
楼上说的也是我想的,不知道楼主想要做什么。
bear234 2015-04-22
  • 打赏
  • 举报
回复
你都new了,为什么不返回指针?
mewiteor 2015-04-22
  • 打赏
  • 举报
回复
引用 8 楼 william7_138 的回复:
[quote=引用 1 楼 mewiteor 的回复:] 可以
A& return_A()
{
     A *a = new A();
     return *a;
}
然后
A& a2=a1.return_A();
之后
delete &a2;
不过在return_A里最好用安全指针,比如
unique_ptr<A> a(new A());
return *a;
然后就不用手动delete了。
这里和这位同学有点不同意见,我觉得即便返回的是引用,其实在return的时候是以bitwise的方式把*a的内容拷贝给了a2,函数返回之后a2仍然无法操作在函数return_A中申请的堆内存,因此还是会有内存泄漏。 建议楼主以后遇到堆内存,还是使用指针操作。[/quote] 实测不会调用拷贝构造函数。
#include<iostream>
#include<iomanip>
using namespace std;
class A
{
	private:
		const char* _s;
	public :
		A(const char* s):_s(s)
		{
			cout<<"constructor:";
			if(s)
				cout<<s;
			cout<<endl;
		}
		A(const A& a)
		{
			_s=a._s;
			cout<<"copy constructor:";
			if(_s)
				cout<<_s;
			cout<<endl;
		}
		A(A&& a)
		{
			_s=a._s;
			a._s=nullptr;
			cout<<"move constructor:";
			if(_s)
				cout<<_s;
			cout<<endl;
		}
		~A()
		{
			cout<<"destructor:";
			if(_s)
			{
				cout<<_s;
				_s=nullptr;
			}
			cout<<endl;
		}
		A& return_A(const char*s)
		{
			cout<<"return_A start"<<endl;
			A* a=new A(s);
			cout<<"return_A end"<<endl;
			return *a;
		}
		const char *getString()
		{
			return _s;
		}
};
int main()
{
	cout<<"start"<<endl;
	A a1("a1");
	cout<<"call return_A start"<<endl;
	A& a2=a1.return_A("a1->a2");
	cout<<"call return_A end"<<endl;
	cout<<"a2._s("<<setbase(ios::hex)<<setw(sizeof(size_t)*2)<<setfill('0')
		<<(size_t)a2.getString()<<") == "<<(a2.getString()?a2.getString():"nullptr")<<endl;
	delete &a2;
	cout<<"a2._s("<<setbase(ios::hex)<<setw(sizeof(size_t)*2)<<setfill('0')
		<<(size_t)a2.getString()<<") == "<<(a2.getString()?a2.getString():"nullptr")<<endl;
	cout<<"end"<<endl;
	return 0;
}
/*
output:
start
constructor:a1
call return_A start
return_A start
constructor:a1->a2
return_A end
call return_A end
a2._s(17232304) == a1->a2
destructor:a1->a2
a2._s(00000000) == nullptr
end
destructor:a1
*/
因为成员函数返回的是引用,定义的a2也是引用类型,所以不会产生新的对象。

65,199

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧