C++ shared_ptr 作为参数和返回值的比较

本文探讨了C++中shared_ptr作为参数和返回值时的行为。值传递会导致引用计数增加,而引用传递则不改变。const修饰的shared_ptr能防止重新赋值,但无法阻止修改对象内容。shared_ptr作为返回值通常因RVO优化而避免额外拷贝。文章通过示例展示了这些概念的实际应用。
摘要由CSDN通过智能技术生成

shared_ptr做参数

值传递和引用传递

智能指针的规则和普通的参数相同,我们可以把它当作是一个普通的类型,不要去想指针的那套规则了。
和普通类型一样,智能指针的值传递比引用传递多了一次内存的拷贝,但是和普通类型的值传递稍微不同的是,值传递时修改实参不会产生问题(这里类比指针)。

下面来看个例子:

void func1(PersonShardPtr p1) 
{
    std::cout << "func1, " << "memory adress:" << &p1 << ", value:" << p1 << ", use_count:" << p1.use_count() << endl;
    p1->a= 100;    
}

void func2(PersonShardPtr& p2) 
{
    std::cout << "func2, " << "memory adress:" << &p2 << ", value:" << p2 << ", use_count:" << p2.use_count() << endl;
    p2->b= 100;
}

int main(int argc, char *argv[])
{
    std::shared_ptr<Person> p = std::make_shared<Person>();
    std::cout << "main1, " << "memory adress:" << &p << ", value:"<< p<< ", use_count:" << p.use_count() << endl;
    func1(p);
    std::cout << "main2, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    func2(p);
    std::cout << "main3, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    std::cout << "main4, " << "a value is:" << p->a << ", b value is:" << p->b << endl;
}

在这里插入图片描述
从代码和运行结果,我们可以看到:
1.调用func1时,p1的内存地址发生了变化,所以引用计数加了1,p2的内存地址不变,所以引用计数不变;
2.p中a和b的值都被成功的修改了。

对于通常的使用来说,值传递和引用传递都能满足我们的要求, 但是在下面的场景值传递会出现问题,我们在const里详细了解一下。

const的作用

首先我们先看一个场景:

void func1(PersonShardPtr p) 
{
    std::cout << "func1, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    p = std::make_shared<Person>();
    p->a= 100;
    
    //return nullptr;
}

void func2(PersonShardPtr& p) 
{
    std::cout << "func2, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    p = std::make_shared<Person>();
    p->b= 100;
    //return nullptr;
}

void func3(const PersonShardPtr p) 
{
    std::cout << "func4, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    //p = std::make_shared<Person>(); //打开这个注释编译会出错,因为声明为const。
    p->c= 100;
}

int main(int argc, char *argv[])
{
    std::shared_ptr<Person> p = std::make_shared<Person>();
    std::cout << "main1, " << "memory adress:" << &p << ", value:"<< p<< ", use_count:" << p.use_count() << endl;
    func1(p);
    std::cout << "main2, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count()<<endl;
    func2(p);
    std::cout << "main3, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    std::cout << "main4, " << "a value is:" << p->a << ", b value is:" << p->b << endl;
    func3(p);
}

在这里插入图片描述
从运行结果我们可以看到func1中p重新分配了内存,所以a的值为1,func2中重新分配内存后,我们发现p的值发生了变化。这个现象和传递指针是一样的。所以const的作用可以防止智能指针指向新的对象,但是注意const不能阻止修改p指向对象的值。

shared_ptr作为返回值

shared_ptr作为返回值没有特别多需要强调了,由于RVO的原因,通常情况下shared_ptr返回值类型就够了,而且返回引用类型需要保证这个shared_ptr不能是临时变量,所以除了特殊使用场景,是没有必要的。
下面看一个例子:

PersonShardPtr func4() 
{
    PersonShardPtr p = std::make_shared<Person>();
    std::cout << "func4, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
    return p;
}

int main(int argc, char *argv[])
{
    PersonShardPtr p = func4();
    std::cout << "main, " << "memory adress:" << &p << ", value:" << p << ", use_count:" << p.use_count() << endl;
}

在这里插入图片描述
可以看到,由于RVO的原因,他们的地址是相同的。
这里提到一点,由于编译器的原因,当我们需要返回空指针的时候,null/nullptr 有可能不会被编译器识别导致编译错误,所以返回空指针建议使用PersonShardPtr();

C++中,函数可以返回一个shared_ptr对象。可以通过以下几种方式来返回shared_ptr对象: 1. 使用make_shared函数:可以使用std::make_shared函数来创建一个shared_ptr对象,并将其作为函数的返回值。例如: ```cpp std::shared_ptr<MyClass> createObject() { return std::make_shared<MyClass>("Hello", 3.14); } ``` 2. 使用new关键字:可以使用new关键字手动创建一个对象,并将其包装在shared_ptr中返回。例如: ```cpp std::shared_ptr<int> createInt() { return std::shared_ptr<int>(new int(1)); } ``` 3. 使用reset函数:可以先创建一个空的shared_ptr对象,然后使用reset函数将其重新指向一个新的对象。例如: ```cpp std::shared_ptr<int> createInt() { std::shared_ptr<int> ptr; ptr.reset(new int(1)); return ptr; } ``` 无论使用哪种方式,函数返回的shared_ptr对象都可以在函数外部进行使用和管理。 #### 引用[.reference_title] - *1* *3* [C++11 解决内存泄露问题的智能指针shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44120785/article/details/128714630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [智能指针shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44477424/article/details/125902769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值