C、C++函数返回值的细微区别

建议:使用指针是最佳原则

C函数返回结构体对象(栈、堆)表现情况:
①返回对象->复制对象
②返回指针->复制地址

C:

#include <stdio.h>
#include <stdlib.h>

struct tst{
	int age;
	const char *name;
};

/**
*返回对象
**/
struct tst get_obj_tst(){
	struct tst s = {.age = 18,.name = "hsj is smart!"};
	// //旧地址
	printf("%p\n",&s);
	return s;
}
/**
*返回指针
**/
struct tst* get_ptr_tst(){
	struct tst* s = (struct tst*)malloc(sizeof(struct tst));
	s->age = 18;
	s->name = "hsj is smart!";
	// //旧地址
	printf("%p\n",s);
	return s;
}
int main(){
	 
	{
	struct tst s = get_obj_tst();
	//新地址
	printf("%p\n",&s);
	printf("%d, %s\n",s.age,s.name);
	}
	printf("----------------------\n");
	{
	struct tst* sp = get_ptr_tst();
	//新地址
	printf("%p\n",sp);
	printf("%d, %s\n",sp->age,sp->name);
	free(sp);
	}
    return 0;
}

在这里插入图片描述

C++函数返回结构体对象、类对象(栈、堆)表现情况:
①返回对象->类似引用(同一个地址)
②返回指针->复制地址
②返回引用->产生碎片,使用[复制构造函数||移动构造函数],原始堆对象有memery_leak内存溢出风险

C++:

#include <iostream>
using namespace std;


class demo{
public:
    demo():num(new int(0)){
        cout<<"construct!"<<endl;
    }
    demo(const demo &d):num(new int(*d.num)){
        cout<<"copy construct!"<<endl;
    }
    //添加移动构造函数
    demo(demo &&d):num(d.num){
        d.num = NULL;
        cout<<"move construct!"<<endl;
    }
    ~demo(){
        cout<<"class destruct!"<<this<<endl;
    }
	int get_num()const;
	void set_num(int new_num);
private:
    int *num;
};
int demo::get_num()const{
	int *num = (*this).num;
	if(num == nullptr){
		return -1;
	}
	return *num;
}
void demo::set_num(int new_num){
	*((*this).num) = new_num;
}


/**
*返回指针
**/
demo* get_ptr_demo(){
    demo* a = new demo();
	a->set_num(100);
	// //旧地址
	cout<<a<<endl;
	return a;
}

/**
*返回对象
**/
demo get_obj_demo(){
	demo a = demo();
	a.set_num(200);
	// //旧地址
	cout<<&a<<endl;
	return a;
}

/**
*返回引用,产生碎片,使用[复制构造函数||移动构造函数],原始堆对象有memery_leak内存溢出风险
* 函数内堆对象建议:返回指针
**/
demo& get_ref_demo(){
    demo* a = new demo();
	a->set_num(300);
	// //旧地址
	cout<<a<<endl;
	return *a;
}

struct tst{
	public:
	int age;
	const char *name;
	
	~tst(){
		cout<<"struct destory"<<this<<endl;
	}
};


/**
*返回指针
**/
struct tst* get_ptr_tst(){
	struct tst* s = new struct tst;
	s->age = 18;
	s->name = "hsj is smart!";
	// //旧地址
	cout<<s<<endl;
	return s;
}

/**
*返回对象
**/
struct tst get_obj_tst(){
	struct tst s = {.age = 18,.name = "hsj is smart!"};
	// //旧地址
	cout<<&s<<endl;
	return s;
}

int main(){
	    {
		demo* a = get_ptr_demo();
		//新地址
	    cout<<a<<endl;
		cout<<a->get_num()<<endl;
		delete a;
	    }
		
		cout<<"-----------------------"<<endl;
		
		{
		demo b = get_obj_demo();
		//新地址
	    cout<<&b<<endl;
		cout<<b.get_num()<<endl;
		}
		
		cout<<"-----------------------"<<endl;
		
		{
		demo c = get_ref_demo();
		demo& d = c;
		//新地址
	    cout<<&c<<endl;
		cout<<&d<<endl;
		cout<<c.get_num()<<endl;
		cout<<d.get_num()<<endl;
		}
		
		cout<<"-----------------------"<<endl;
		
		{
		struct tst* s = get_ptr_tst();
		//新地址
	    cout<<s<<endl;
		cout<<s->age<<"\t"<<s->name<<endl;
		delete s;
		}
		
		cout<<"-----------------------"<<endl;
		
		{
		struct tst s = get_obj_tst();
		//新地址
	    cout<<&s<<endl;
		cout<<s.age<<"\t"<<s.name<<endl;
		}
		
		cout<<"-----------------------"<<endl;

	
    return 0;
}

在这里插入图片描述
是不是很奇怪?C++为什么没有使用【复制构造函数||移动复制构造函数】?其原因是:RVO(return value optimization),被G++进行值返回的优化了,具体的RVO的相关技术,可以进行百度。
我们可以将RVO优化关闭,可以对g++增加选项-fno-elide-constructors,重新编绎之后。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值