建议:使用指针是最佳原则
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,重新编绎之后。