前几天看的webrtc实际上一直是libjingle的talk,base目录下的基础性东西,似乎是google在原来的webrtc的代码中又做了一些改进。现在由于工作的需要,所有的眼光都集中到webrtc上了,让我也不得不将精力向webrtc的代码靠拢。
最近几天的文章不会涉及到任何关于webrtc框架的东西,何况我也不懂框架,仅仅是对webrtc一些基础类的封装的使用的库,学鲁迅的拿来主义,读懂,然后据为己有,然后在自己的以后的编程中应用上面的思想进行改进。
今天主要讨论scoped_ptr,先上代码:
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
//
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the scoped_ptr or via
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
// use shared_ptr or std::auto_ptr if your needs are more complex.
// scoped_ptr_malloc added in by Google. When one of
// these goes out of scope, instead of doing a delete or delete[], it
// calls free(). scoped_ptr_malloc is likely to see much more
// use than any other specializations.
// release() added in by Google. Use this to conditionally
// transfer ownership of a heap-allocated object to the caller, usually on
// method success.
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
#include // for assert
#include // for free() decl
#include // for std::ptrdiff_t
#ifdef _WIN32
namespace std { using ::ptrdiff_t; };
#endif // _WIN32
namespace webrtc {
template
class scoped_ptr {
private:
T* ptr;
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
public:
typedef T element_type;
explicit scoped_ptr(T* p = NULL): ptr(p) {}
~scoped_ptr() {
typedef char type_must_be_complete[sizeof(T)];
delete ptr;
}
void reset(T* p = NULL) {
typedef char type_must_be_complete[sizeof(T)];
if (ptr != p) {
T* obj = ptr;
ptr = p;
// Delete last, in case obj destructor indirectly results in ~scoped_ptr
delete obj;
}
}
T& operator*() const {
assert(ptr != NULL);
return *ptr;
}
T* operator->() const {
assert(ptr != NULL);
return ptr;
}
T* get() const {
return ptr;
}
void swap(scoped_ptr & b) {
T* tmp = b.ptr;
b.ptr = ptr;
ptr = tmp;
}
T* release() {
T* tmp = ptr;
ptr = NULL;
return tmp;
}
T** accept() {
if (ptr) {
delete ptr;
ptr = NULL;
}
return &ptr;
}
T** use() {
return &ptr;
}
};
template inline
void swap(scoped_ptr& a, scoped_ptr& b) {
a.swap(b);
}
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
// is guaranteed, either on destruction of the scoped_array or via an explicit
// reset(). Use shared_array or std::vector if your needs are more complex.
template
class scoped_array {
private:
T* ptr;
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
public:
typedef T element_type;
explicit scoped_array(T* p = NULL) : ptr(p) {}
~scoped_array() {
typedef char type_must_be_complete[sizeof(T)];
delete[] ptr;
}
void reset(T* p = NULL) {
typedef char type_must_be_complete[sizeof(T)];
if (ptr != p) {
T* arr = ptr;
ptr = p;
// Delete last, in case arr destructor indirectly results in ~scoped_array
delete [] arr;
}
}
T& operator[](std::ptrdiff_t i) const {
assert(ptr != NULL);
assert(i >= 0);
return ptr[i];
}
T* get() const {
return ptr;
}
void swap(scoped_array & b) {
T* tmp = b.ptr;
b.ptr = ptr;
ptr = tmp;
}
T* release() {
T* tmp = ptr;
ptr = NULL;
return tmp;
}
T** accept() {
if (ptr) {
delete [] ptr;
ptr = NULL;
}
return &ptr;
}
};
template inline
void swap(scoped_array& a, scoped_array& b) {
a.swap(b);
}
// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
// second template argument, the function used to free the object.
template class scoped_ptr_malloc {
private:
T* ptr;
scoped_ptr_malloc(scoped_ptr_malloc const &);
scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
public:
typedef T element_type;
explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
~scoped_ptr_malloc() {
FF(static_cast(ptr));
}
void reset(T* p = 0) {
if (ptr != p) {
FF(static_cast(ptr));
ptr = p;
}
}
T& operator*() const {
assert(ptr != 0);
return *ptr;
}
T* operator->() const {
assert(ptr != 0);
return ptr;
}
T* get() const {
return ptr;
}
void swap(scoped_ptr_malloc & b) {
T* tmp = b.ptr;
b.ptr = ptr;
ptr = tmp;
}
T* release() {
T* tmp = ptr;
ptr = 0;
return tmp;
}
T** accept() {
if (ptr) {
FF(static_cast(ptr));
ptr = 0;
}
return &ptr;
}
};
template inline
void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) {
a.swap(b);
}
} // namespace webrtc
#endif // #ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SCOPED_PTR_H_
scoped_ptr是为了方便的管理指针而使用的,它有一个数据成员ptr,它拥有者这个指针的所有权,并负责释放它,客户不用去管。
它可以像普通的指针一样使用,主要由于重载了operator*(),operator->(),运算符
它可以返回ptr供客户使用。通过get方法,但是一定要注意,它仅仅返回指针,而并不返回所有权。也就是说下面的这段代码:
scoped_ptr
int *p = sp.get();
delete p;
这段代码是错误的,由于p并没有获得int变量的所有权,它也就无权释放它
它可以手工的去释放ptr,通过sp.reset().
它可以用于管理另一个之后指针,通过sp.reset(another_ptr);
它可以和另一个scoped_ptr交换所有权。
它可以自动释放管理的指针,通过析构函数
它不可以被赋值,被copy,是因为它的这两个函数私有声明了。
它采用的是栈内存管理堆内存的思想,这个思想在后面介绍锁的使用也有体现。
通常情况下我们会这样使用它:
class ViEExternalRendererImpl
{
scoped_ptr converted_frame_;
}
ViEExternalRendererImpl::ViEExternalRendererImpl()
:converted_frame_(new VideoFrame()) {
}
必须在构造函数的成员初始化列表中负责对scoped_ptr对象进行初始化。