很多理论介绍的很好了,但看了后还是难以下手。
有时候实际的例子更有代入感,本文主要介绍项目中实际的智能指针应用例子。
一 局部函数中使用
几乎所有资料,介绍的都是智能指针在局部函数中的使用
0) 直接定义方式
整形智能指针
<code> unique_ptr bits(new uint8_t[size.cx * size.cy * 4]); memset(bits.get(), 0, size.cx * size.cy * 4);// 一定要初始化 不然 透明色 很可能是半透明色 Gdiplus::Bitmap bitmap(size.cx, size.cy, 4 * size.cx, PixelFormat32bppARGB, bits.get());/<code>
类变量智能指针
<code> std::unique_ptr enc(new Encoder(encoder, bitrate, channels, sampleRate, bitsPerSample)); if (!enc->Initialize()) return nullptr; return enc.release();/<code>
vector数组 智能指针
<code> std::unique_ptr> data(new std::vector()); ComPtr type; std::unique_ptr frame;/<code>
数组 智能指针
<code> std::unique_ptr pDimensionIDs(new GUID[nCount]); src_image_->GetFrameDimensionsList(pDimensionIDs.get(), nCount); int iFrameCount = src_image_->GetFrameCount(&pDimensionIDs.get()[0]);/<code>
初始化列表的方式 也就是大括号方式 初始化赋值
<code>unique_ptr obj{obs_data_item_byname(settings, name)};/<code>
<code> auto data_deleter = [](obs_data_t *d) { obs_data_release(d); }; using data_t = unique_ptr; data_t content{obs_data_create(), data_deleter}; data_t files{obs_data_create(), data_deleter}; data_t request{obs_data_create(), data_deleter};/<code>
1)reset方式
<code> unique_ptr ca; try { ca.reset(new ca_encoder()); } catch (...) { CA_LOG_ENCODER("AAC", encoder, LOG_ERROR, "Could not allocate encoder"); return nullptr; } ca->encoder = encoder; ca->format_name = "AAC";/<code>
2)Initializer list
<code> auto DestroyProperties = [](obs_properties_t *props) { obs_properties_destroy(props); }; std::unique_ptr props{ obs_get_encoder_properties(id), DestroyProperties}; if (!props) { blog(LOG_ERROR, "Failed to get properties for encoder " "'%s' (%s)", EncoderName(id), id); return; }/<code>
<code> auto ReleaseData = [](obs_data_t *data) { obs_data_release(data); }; std::unique_ptr data{ obs_encoder_defaults(id), ReleaseData};/<code>
二 类中声明智能指针
1) 通过reset设置
1.1)
<code>struct TextSource { obs_source_t *source = nullptr; gs_texture_t *tex = nullptr; uint32_t cx = 0; uint32_t cy = 0; HDCObj hdc; Graphics graphics; HFONTObj hfont; unique_ptr font;/<code>
<code> hfont = nullptr; font.reset(nullptr); font.reset(new Font(hdc, hfont));/<code>
完整的例子
<code>void TextSource::UpdateFont() { hfont = nullptr; font.reset(nullptr); LOGFONT lf = {}; lf.lfHeight = face_size; lf.lfWeight = bold ? FW_BOLD : FW_DONTCARE; lf.lfItalic = italic; lf.lfUnderline = underline; lf.lfStrikeOut = strikeout; lf.lfQuality = ANTIALIASED_QUALITY; lf.lfCharSet = DEFAULT_CHARSET; if (!face.empty()) { wcscpy(lf.lfFaceName, face.c_str()); hfont = CreateFontIndirect(&lf); } if (!hfont) { wcscpy(lf.lfFaceName, L"Arial"); hfont = CreateFontIndirect(&lf); } if (hfont) font.reset(new Font(hdc, hfont)); }/<code>
1.2)
<code> std::unique_ptr modal_dlg_;/<code>
<code>bool AsyncModalRunner::DoModal(ModalWndBase *dlg) { assert(!is_running_); modal_dlg_.reset(dlg);/<code>
<code> if (modal_dlg_ != nullptr) { modal_dlg_->SyncShowModal(); }/<code>
1.3
<code> std::unique_ptr brush_; Brush_Gdiplus::Brush_Gdiplus(DWORD color) : IBrush(color) { brush_.reset(new SolidBrush(color)); } Brush_Gdiplus::Brush_Gdiplus(const Brush_Gdiplus& r) : IBrush(r) { if (r.brush_) brush_.reset(r.brush_->Clone()); if (r.bitmap_brush_) bitmap_brush_.reset(r.bitmap_brush_->Clone()); }/<code>
2)初始化列表中赋值
2.1)
<code>protected: std::unique_ptr m_pLayout;/<code>
<code>Box::Box(Layout* pLayout) : m_pLayout(pLayout), // m_bAutoDestroy(true), m_bDelayedDestroy(true), m_bMouseChildEnabled(true), m_items(), OnBubbledEvent() { m_pLayout->SetOwner(this); } Box::Box(const Box& r) : Control(r), m_bAutoDestroy(r.m_bAutoDestroy), m_bDelayedDestroy(r.m_bDelayedDestroy), m_bMouseChildEnabled(r.m_bMouseChildEnabled), m_items(), OnBubbledEvent() { m_pLayout.reset(new Layout(*r.m_pLayout)), // m_pLayout->SetOwner(this); }/<code>
2.2)
<code>class OBSBasicInteraction : public QDialog { Q_OBJECT private: OBSBasic *main; std::unique_ptr ui; OBSSource source; OBSSignal removedSignal; OBSSignal renamedSignal; std::unique_ptr eventFilter;/<code>
<code>OBSBasicInteraction::OBSBasicInteraction(QWidget *parent, OBSSource source_) : QDialog (parent), main (qobject_cast(parent)), ui (new Ui::OBSBasicInteraction), source (source_), removedSignal (obs_source_get_signal_handler(source), "remove", OBSBasicInteraction::SourceRemoved, this), renamedSignal (obs_source_get_signal_handler(source), "rename", OBSBasicInteraction::SourceRenamed, this), eventFilter (BuildEventFilter()) //... OBSEventFilter *OBSBasicInteraction::BuildEventFilter() { return new OBSEventFilter( [this](QObject *obj, QEvent *event) { UNUSED_PARAMETER(obj); switch(event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: return this->HandleMouseClickEvent( static_cast(event)); case QEvent::MouseMove: case QEvent::Enter: case QEvent::Leave: return this->HandleMouseMoveEvent( static_cast(event)); case QEvent::Wheel: return this->HandleMouseWheelEvent( static_cast(event)); case QEvent::FocusIn: case QEvent::FocusOut: return this->HandleFocusEvent( static_cast(event)); case QEvent::KeyPress: case QEvent::KeyRelease: return this->HandleKeyEvent( static_cast(event)); default: return false; } }); }/<code>
<code> QPointer interaction; void OBSBasic::CreateInteractionWindow(obs_source_t *source) { if (interaction) interaction->close(); interaction = new OBSBasicInteraction(this, source); interaction->Init(); interaction->setAttribute(Qt::WA_DeleteOnClose, true); } /<code>
3)通过std::move 将局部智能指针控制权,转移到类智能指针
<code> struct H264Frame { public: H264Frame(bool keyframe, UINT64 pts, UINT64 dts, std::unique_ptr> data) : keyframe(keyframe), pts(pts), dts(dts), data(std::move(data)) {} bool Keyframe() { return keyframe; } BYTE *Data() { return data.get()->data(); } DWORD DataLength() { return (DWORD)data.get()->size(); } INT64 Pts() { return pts; } INT64 Dts() { return dts; } private: H264Frame(H264Frame const&) = delete; H264Frame& operator=(H264Frame const&) = delete; private: bool keyframe; INT64 pts; INT64 dts; std::unique_ptr> data; }; /<code>
下面看看这个data是如何赋值的呢?
首先,在局部函数中,创建一个同类型的智能指针
<code>std::unique_ptr> data(new std::vector());/<code>
这个vector插入插入数据运算
<code>data->insert(data->end(), &bufferData[0], &bufferData[bufferLength]);/<code>
最后,通过std::move,将智能指针转移给类成员变量
<code>//构造函数 struct H264Frame { public: H264Frame(bool keyframe, UINT64 pts, UINT64 dts, std::unique_ptr> data) : keyframe(keyframe), pts(pts), dts(dts), data(std::move(data)) //将局部智能指针,转移到类智能指针中 frame.reset(new H264Frame(keyframe, samplePts / sampleDur, sampleDts / sampleDur, std::move(data)));/<code>
- 返回值是unique_ptr
1)
<code>static std::unique_ptr CreateDescriptor( ComPtr activate) { UINT32 flags; if (FAILED(activate->GetUINT32(MF_TRANSFORM_FLAGS_Attribute, &flags))) return nullptr; bool isAsync = !(flags & MFT_ENUM_FLAG_SYNCMFT); isAsync |= !!(flags & MFT_ENUM_FLAG_ASYNCMFT); bool isHardware = !!(flags & MFT_ENUM_FLAG_HARDWARE); GUID guid = {0}; if (FAILED(activate->GetGUID(MFT_TRANSFORM_CLSID_Attribute, &guid))) return nullptr; ComHeapPtr guidW; StringFromIID(guid, &guidW); std::string guidString = MBSToString(guidW); auto pred = [guidString](const EncoderEntry &name) { return guidString == name.guid; }; EncoderEntry *entry = std::find_if(std::begin(guidNameMap), std::end(guidNameMap), pred); std::unique_ptr descriptor(new EncoderDescriptor( activate, entry->name, entry->id, guid, guidString, isAsync, isHardware, entry->type)); return descriptor; }/<code>
<code> std::vector> descriptors; for (decltype(count) i = 0; i < count; i++) { auto p = std::move(CreateDescriptor(ppActivate[i])); if (p) descriptors.emplace_back(std::move(p)); }/<code>
1 初始化列表中 初始化
<code>std::unique_ptr ui;/<code>
<code>SceneSwitcher::SceneSwitcher(QWidget *parent) : QDialog(parent), ui(new Ui_SceneSwitcher)/<code>
2 匿名函数 自定义删除器
<code>struct obs_data { volatile long ref; char *json; struct obs_data_item *first_item; }; typedef struct obs_data obs_data_t;/<code>
<code> auto ReleaseData = [](obs_data_t *data) { obs_data_release(data); }; std::unique_ptr data{ obs_encoder_defaults(id), ReleaseData};/<code>
<code>static void HandleSampleRate(obs_property_t* prop, const char *id) { auto ReleaseData = [](obs_data_t *data) { obs_data_release(data); }; std::unique_ptr data{ obs_encoder_defaults(id), ReleaseData}; if (!data) { blog(LOG_ERROR, "Failed to get defaults for encoder '%s' (%s) " "while populating bitrate map", EncoderName(id), id); return; } auto main = reinterpret_cast(App()->GetMainWindow()); if (!main) { blog(LOG_ERROR, "Failed to get main window while populating " "bitrate map"); return; } uint32_t sampleRate = config_get_uint(main->Config(), "Audio", "SampleRate"); obs_data_set_int(data.get(), "samplerate", sampleRate); obs_property_modified(prop, data.get()); }/<code>
三 容器元素
1) map
<code>std::map> m_animationMap;/<code>
初始化列表中初始化
<code>AnimationManager::AnimationManager() : m_pControl(nullptr), m_animationMap() { }/<code>
<code>AnimationPlayer* AnimationManager::SetFadeHot(bool bFadeHot) { AnimationPlayer* animationArgs = nullptr; if (bFadeHot) { animationArgs = new AnimationPlayer(); animationArgs->SetStartValue(0); animationArgs->SetEndValue(255); animationArgs->SetSpeedUpRatio(0.3); animationArgs->SetSpeedDownRatio(0.7); animationArgs->SetTotalMillSeconds(250); std::function playCallback = nbase::Bind(&Control::SetHotAlpha, m_pControl, std::placeholders::_1); animationArgs->SetCallback(playCallback); m_animationMap[kAnimationHot].reset(animationArgs); } else { m_animationMap.erase(kAnimationHot); } return animationArgs; } /<code>
四 作为参数,返回值
1)作为参数
通过引用的方式传递
<code>struct gs_pixel_shader : gs_shader { ComPtr shader; vector> samplers;/<code>
<code>void ShaderProcessor::BuildSamplers(vector> &samplers) { for (size_t i = 0; i < parser.samplers.num; i++) AddSampler(device, parser.samplers.array[i], samplers); }/<code>
<code>static inline void AddSampler(gs_device_t *device, shader_sampler &sampler, vector> &samplers) { gs_sampler_info si; shader_sampler_convert(&sampler, &si); samplers.emplace_back(new ShaderSampler(sampler.name, device, &si)); } /<code>
<code>gs_pixel_shader::gs_pixel_shader(gs_device_t *device, const char *file, const char *shaderString) : gs_shader(device, gs_type::gs_pixel_shader, GS_SHADER_PIXEL) { ShaderProcessor processor(device); ComPtr shaderBlob; string outputString; HRESULT hr; processor.Process(shaderString, file); processor.BuildString(outputString); processor.BuildParams(params); processor.BuildSamplers(samplers);/<code>
2)返回值
通过std::move转移控制权
<code>static std::unique_ptr CreateDescriptor( ComPtr activate) { std::unique_ptr descriptor(new EncoderDescriptor( activate, entry->name, entry->id, guid, guidString, isAsync, isHardware, entry->type)); return descriptor; } for (decltype(count) i = 0; i < count; i++) { auto p = std::move(CreateDescriptor(ppActivate[i])); if (p) descriptors.emplace_back(std::move(p)); }/<code>
对于shared类型,可以直接返回
<code>std::vector> EncoderDescriptor::Enumerate() { HRESULT hr; UINT32 count = 0; std::vector> descriptors; if (SUCCEEDED(hr)) { for (decltype(count) i = 0; i < count; i++) { auto p = std::move(CreateDescriptor(ppActivate[i])); if (p) descriptors.emplace_back(std::move(p)); } } return descriptors; } auto encoders = EncoderDescriptor::Enumerate(); for (auto e : encoders) { /* ignore the software encoder due to the fact that we already * have an objectively superior software encoder available */ if (e->Type() == EncoderType::H264_SOFTWARE) continue;/<code>
五 自定义删除器
1 匿名函数方式
1)匿名函数 大括号的方式赋值
<code> auto data_deleter = [](obs_data_t *d) { obs_data_release(d); }; using data_t = unique_ptr; data_t content{obs_data_create(), data_deleter}; data_t files{obs_data_create(), data_deleter}; data_t request{obs_data_create(), data_deleter}; /<code>
2)
<code> auto ReleaseData = [](obs_data_t *data) { obs_data_release(data); }; std::unique_ptr data{ obs_encoder_defaults(id), ReleaseData};/<code>
3)
<code> auto DestroyProperties = [](obs_properties_t *props) { obs_properties_destroy(props); }; std::unique_ptr props{ obs_get_encoder_properties(id), DestroyProperties}; if (!props) { blog(LOG_ERROR, "Failed to get properties for encoder " "'%s' (%s)", EncoderName(id), id); return; }/<code>
4) 全局静态匿名函数
<code>static auto ProfilerFree = [](void *) { profiler_stop(); auto snap = GetSnapshot(); profiler_print(snap.get()); profiler_print_time_between_calls(snap.get()); SaveProfilerData(snap); profiler_free(); }; /<code>
<code> std::unique_ptr prof_release(static_cast(&ProfilerFree), ProfilerFree);/<code>
2 类重载() 实现删除器
<code>class OBSFFDeleter { public: void operator()(const ff_format_desc *format) { ff_format_desc_free(format); } void operator()(const ff_codec_desc *codec) { ff_codec_desc_free(codec); } }; using OBSFFCodecDesc = std::unique_ptr; using OBSFFFormatDesc = std::unique_ptr; OBSFFFormatDesc formats;/<code>
成员函数中,直接reset() 不用再写具体删除器 就可以了
<code> formats.reset(ff_format_supported()); const ff_format_desc *format = formats.get();/<code>
不过如果以列表方式初始化,还要写删除器,如:
<code>static auto SnapshotRelease = [](profiler_snapshot_t *snap) { profile_snapshot_free(snap); }; using ProfilerSnapshot = std::unique_ptr; ProfilerSnapshot GetSnapshot() { return ProfilerSnapshot{profile_snapshot_create(), SnapshotRelease}; } auto snap = GetSnapshot(); profiler_print(snap.get());/<code>
六 自己的例子
<code> struct DataDelete { void operator() (obs_data_t* d) { obs_data_release(d); } }; std::unique_ptr pNewSourceSettings;/<code>
<code> pNewSourceSettings.reset(obs_data_create()); obs_data_set_int(pNewSourceSettings.get(), "nType", nIndex);/<code>
参考资料:
https://blog.csdn.net/lijinqi1987/article/details/79005794
https://blog.csdn.net/afei__/article/details/80670283