前幾天看的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 _WIN32namespace std { using ::ptrdiff_t; };#endif // _WIN32namespace 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> inlinevoid 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> inlinevoid 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*)> inlinevoid 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對象,它管理者VideoFrame指標。
必須在建構函式的成員初始化列表中負責對scoped_ptr對象進行初始化。