智能指针(Android强指针)引用类型拷贝
Posted
技术标签:
【中文标题】智能指针(Android强指针)引用类型拷贝【英文标题】:smart pointer (Android strong pointer) reference type copy 【发布时间】:2017-08-11 09:20:50 【问题描述】:我无法弄清楚 android 框架(在 C++ 中)的以下区别
class foo
...
class child_foo : public foo
...
sp<child_foo> item = new child_foo;
const sp<foo> &r1 = item;
那么item的强计数是2。
但是,如果它在
sp<child_foo> item = new child_foo;
const sp<child_foo> &r1 = item;
那么item的强计数是1。
它们有什么区别?
我还注意到const sp<foo> &r2 = item;
会调用 sp's(original typo of foo's) 构造函数,为什么?
在这里修复,不是 foo 的构造函数,而是 sp(强指针)。
提前致谢!
【问题讨论】:
对智能指针的引用不会增加智能指针的引用计数。您只需为智能指针创建一个别名(第二个示例)。不确定为什么调用 foo 的构造函数。我猜你在这里混淆了,因为如果在第一个例子中创建了一个新的 foo 对象并且引用计数增加了,那就很奇怪了。 【参考方案1】:sp<foo>
引用不能直接绑定到 sp<child_foo>
,因为它是不同的类型。但是编译器可以从sp<child_foo>
构造一个临时的sp<foo>
来进行转换。并且因为 const 引用可以延长临时的生命周期,所以这个临时可以绑定到 const 引用。强计数为 2,因为有两个 sp
、item
和临时的。
在第二种情况下,const 引用可以直接绑定到sp<child_foo>
,因为它们是相同的类型,并且没有创建临时值,并且强计数保持在 1。
【讨论】:
【参考方案2】:我想在这里添加一些 cmets。
我对这个问题很感兴趣,因为它出现的地方似乎很多。
首先很抱歉,因为你需要修正我的描述。
我还注意到 const sp &r2 = item;将调用 sp 的 构造函数,为什么?
调用的构造函数如下。
https://android.googlesource.com/platform/frameworks/native/+/jb-dev/include/utils/StrongPointer.h
template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
if (other) ((T*)other)->incStrong(this);
这个逻辑出现在很多地方,例如:
status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder)
...
mLooper->registerHandler(this);
...
然后查看ALooper.cpp的registerHandler https://android.googlesource.com/platform/frameworks/av/+/7296123/media/libstagefright/foundation/ALooper.cpp
ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler)
return gLooperRoster.registerHandler(this, handler);
引用传递的效果和
一样const sp<foo> &r1 = item;
将引用计数增加 1。
最后,
gLooperRoster.registerHandler(this, handler)
其实调用 https://android.googlesource.com/platform/frameworks/av/+/b6f7642496f955da04d1eb9e33df0dab653c9c4e/media/libstagefright/foundation/ALooperRoster.cpp
ALooper::handler_id ALooperRoster::registerHandler(
const sp<ALooper> looper, const sp<AHandler> &handler)
Mutex::Autolock autoLock(mLock);
if (handler->id() != 0)
CHECK(!"A handler must only be registered once.");
return INVALID_OPERATION;
HandlerInfo info;
info.mLooper = looper;
info.mHandler = handler;
ALooper::handler_id handlerID = mNextHandlerID++;
mHandlers.add(handlerID, info);
handler->setID(handlerID);
return handlerID;
此时,第二次通过引用不会增加引用计数。
为了澄清这一点,我模拟了继承层,因为 MediaCodec 继承了 AHandler。因此,第一次调用是将子指针分配给强指针的引用类型,强指针是父类型的模板。
如果你对它感兴趣,可以试试看。
谢谢。
【讨论】:
以上是关于智能指针(Android强指针)引用类型拷贝的主要内容,如果未能解决你的问题,请参考以下文章