如何将shared_ptr作为参数传递给可变对象
How to pass a shared_ptr to a mutable object as a parameter?
我想通过智能指针引用将对象传递给函数。函数可以更改被引用对象的值,但不能更改引用本身。有两种明显的方法可以解决这个问题。
通过值传递shared_ptr的第一种方法是引用,因此本身不需要通过引用传递。这样做的明显问题是复制引用,这表明存在一些引用计数开销。
void foo (shared_ptr<bar> p)
第二种方法是通过const引用传递shared_ptr,避免复制shared_ptr实例,但意味着对被引用对象的访问需要两层解引用,而不是一层。
void foo (const shared_ptr<bar> &p)
在实践中,这些理论开销通常是微不足道的。这向我表明,与其为每个个案选择一种或另一种方法,我几乎应该始终遵循一些标准惯例。这就引出了一个问题。。。
有没有一个标准的惯例,我通常应该选择这些方法中的哪一种?如果是这样,传统的选择是什么?
EDIT-可能值得一提-考虑按常量引用传递的一个原因是,有一个预先存在的约定,即大多数类/结构实例都是按常量引用而不是按值传递的,并且shared_ptr
是一个类。当然,它不是一个重量级的类别(复制的成本很小(,所以旧惯例背后的原因可能不适用。
始终按值传递shared_ptr
s。如果传递引用,您可能会遇到这样的问题:对shared_ptr
管理的对象的函数的调用可能只会重置它,现在您有一个悬空指针。如果通过值传递,则可以确保对象在当前函数调用中仍然存在。
请参阅此处了解更多信息。
示例:
#include <memory>
#include <iostream>
std::shared_ptr<int> ptr(new int(42));
void foo(){
ptr.reset();
}
void bar(std::shared_ptr<int> const& p){
foo();
std::cout << *p;
}
int main(){
bar(ptr);
}
对此应持谨慎态度。它可以用来证明任何类型都不应该通过const引用传递——例如,请参阅http://ideone.com/1IYyCBenjamin Lindley在评论中指出。
然而,这类问题的更复杂的变化确实是在实践中偶然出现的。例如,这就是为什么我们被警告迭代器(以及const引用返回值(会被变异引用容器的方法无效的原因。一般来说,这些规则很容易遵循,但偶尔更间接和意想不到的例子会让人大吃一惊。
在这种情况下,最好在不需要的时候避免额外的引用层。
如果函数操作对象,则如果对象包含在智能指针中,则该函数应该不相关。它应该接受T&
。操纵值的自由函数被一些人认为是糟糕的风格。通过引用const获取对象并返回一个新值可以更干净。
我一直在传递const&基于这样一种想法,即在调用堆栈的某个地方,应该有人持有sharedptr的副本,因此在我的整个执行过程中,它的寿命是有保障的。
如果您在另一个线程上执行,则需要一个副本,因此存储shared_ptr的任何人(不仅仅是在方法期间使用它(都需要存储副本,而不是引用。
而且,既然我已经写了这篇文章,我将去阅读为什么人们似乎支持相反的心态。
@Xeo所说的一个例子:
void foo(shared_ptr<bar> &p)
{
p.reset(); // ref_count == 0; memory is freed.
}
shared_ptr<bar> p(new bar); // ref_count == 1
foo(p);
const shared_ptr<bar> &p
不会出现这种情况。
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 如何将对象数组作为参数传递给模板
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 对象作为参数传递,就好像我们正在传递构造函数值一样
- 初始化对象以在 C++08 中作为参数传递的首选语法是什么?
- 将对象作为参数传递,没有可行的重载"="
- 当我按值传递参数时对象被破坏时?
- 在将匿名对象作为参数传递时,不会调用任何构造函数
- 是否可以创建一个指向对象的智能指针并将此智能指针作为参数传递给构造函数?
- C++:将对象作为参数传递
- 将 std::ofstream 对象作为参数传递给类方法
- 将对象向量的指针作为参数传递,但差异更大
- 当数组对象以函数参数传递时,为什么复制构造函数会自称
- 如何将对象作为参数传递
- 将对象作为C 中的参数传递
- 将新对象的名称作为参数传递
- 将对象数组作为参数传递的最佳方法是什么
- 为什么将临时对象作为参数传递需要 std::move?
- 将任何数据类型/对象作为参数传递以确定其大小