前几天看的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<char> 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 <assert.h> // for assert #include <stdlib.h> // for free() decl #include <cstddef> // for std::ptrdiff_t #ifdef _WIN32 namespace std { using ::ptrdiff_t; }; #endif // _WIN32 namespace webrtc { template <typename T> 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<typename T> inline void swap(scoped_ptr<T>& a, scoped_ptr<T>& 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<typename T> 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<class T> inline void swap(scoped_array<T>& a, scoped_array<T>& 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<typename T, void (*FF)(void*) = free> 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<void*>(ptr)); } void reset(T* p = 0) { if (ptr != p) { FF(static_cast<void*>(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<void*>(ptr)); ptr = 0; } return &ptr; } }; template<typename T, void (*FF)(void*)> inline void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& 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> sp(new int(100));
int *p = sp.get();
delete p;
这段代码是错误的,由于p并没有获得int变量的所有权,它也就无权释放它
它可以手工的去释放ptr,通过sp.reset().
它可以用于管理另一个之后指针,通过sp.reset(another_ptr);
它可以和另一个scoped_ptr交换所有权。
它可以自动释放管理的指针,通过析构函数
它不可以被赋值,被copy,是因为它的这两个函数私有声明了。
它采用的是栈内存管理堆内存的思想,这个思想在后面介绍锁的使用也有体现。
通常情况下我们会这样使用它:
class ViEExternalRendererImpl { scoped_ptr<VideoFrame> converted_frame_; } ViEExternalRendererImpl::ViEExternalRendererImpl() :converted_frame_(new VideoFrame()) { }
必须在构造函数的成员初始化列表中负责对scoped_ptr对象进行初始化。