c++智能指針示例


c++智能指针示例


很多理论介绍的很好了,但看了后还是难以下手。

有时候实际的例子更有代入感,本文主要介绍项目中实际的智能指针应用例子。


一 局部函数中使用

几乎所有资料,介绍的都是智能指针在局部函数中的使用


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>
c++智能指针示例


类变量智能指针

<code>
	std::unique_ptr enc(new Encoder(encoder,
			bitrate, channels, sampleRate, bitsPerSample));

	if (!enc->Initialize())
		return nullptr;

	return enc.release();/<code>
c++智能指针示例


vector数组 智能指针

<code>	std::unique_ptr> data(new std::vector());
	ComPtr type;
	std::unique_ptr frame;/<code>
c++智能指针示例

数组 智能指针

<code>	std::unique_ptr pDimensionIDs(new GUID[nCount]);
	src_image_->GetFrameDimensionsList(pDimensionIDs.get(), nCount);
	int iFrameCount = src_image_->GetFrameCount(&pDimensionIDs.get()[0]);/<code>
c++智能指针示例


初始化列表的方式 也就是大括号方式 初始化赋值

<code>unique_ptr obj{obs_data_item_byname(settings, name)};/<code>
c++智能指针示例

<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>
c++智能指针示例


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>
c++智能指针示例


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>
c++智能指针示例


<code>	auto ReleaseData = [](obs_data_t *data)
	{
		obs_data_release(data);
	};
	std::unique_ptr data{
			obs_encoder_defaults(id),
			ReleaseData};/<code>
c++智能指针示例


二 类中声明智能指针


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>
c++智能指针示例

<code>	hfont = nullptr;
	font.reset(nullptr);

	font.reset(new Font(hdc, hfont));/<code>
c++智能指针示例


完整的例子

<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>
c++智能指针示例

1.2)

<code>	std::unique_ptr modal_dlg_;/<code>
c++智能指针示例

<code>bool AsyncModalRunner::DoModal(ModalWndBase *dlg)
{
	assert(!is_running_);
	modal_dlg_.reset(dlg);/<code>
c++智能指针示例

<code>	if (modal_dlg_ != nullptr) {
		modal_dlg_->SyncShowModal();
	}/<code>
c++智能指针示例


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>
c++智能指针示例


2)初始化列表中赋值

2.1)

<code>protected:
	std::unique_ptr m_pLayout;/<code>
c++智能指针示例

<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>
c++智能指针示例


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>
c++智能指针示例


<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>
c++智能指针示例


<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>
c++智能指针示例


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>
c++智能指针示例


下面看看这个data是如何赋值的呢?

首先,在局部函数中,创建一个同类型的智能指针

<code>std::unique_ptr> data(new std::vector());/<code>
c++智能指针示例

这个vector插入插入数据运算

<code>data->insert(data->end(), &bufferData[0], &bufferData[bufferLength]);/<code>
c++智能指针示例

最后,通过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>
c++智能指针示例


  • 返回值是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>
c++智能指针示例


<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>
c++智能指针示例


1 初始化列表中 初始化

<code>std::unique_ptr ui;/<code>
c++智能指针示例

<code>SceneSwitcher::SceneSwitcher(QWidget *parent)
	: QDialog(parent),
	  ui(new Ui_SceneSwitcher)/<code>
c++智能指针示例


2 匿名函数 自定义删除器


<code>struct obs_data {
	volatile long        ref;
	char                 *json;
	struct obs_data_item *first_item;
};

typedef struct obs_data       obs_data_t;/<code>
c++智能指针示例


<code>	auto ReleaseData = [](obs_data_t *data)
	{
		obs_data_release(data);
	};
	std::unique_ptr data{
			obs_encoder_defaults(id),
			ReleaseData};/<code>
c++智能指针示例


<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>
c++智能指针示例


三 容器元素

1) map

<code>std::map> m_animationMap;/<code>
c++智能指针示例

初始化列表中初始化

<code>AnimationManager::AnimationManager() : m_pControl(nullptr), m_animationMap()
{

}/<code>
c++智能指针示例

<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>
c++智能指针示例


四 作为参数,返回值


1)作为参数

通过引用的方式传递

<code>struct gs_pixel_shader : gs_shader {
	ComPtr shader;
	vector> samplers;/<code>
c++智能指针示例


<code>void ShaderProcessor::BuildSamplers(vector> &samplers)
{
	for (size_t i = 0; i < parser.samplers.num; i++)
		AddSampler(device, parser.samplers.array[i], samplers);
}/<code>
c++智能指针示例

<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>
c++智能指针示例

<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>
c++智能指针示例


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>
c++智能指针示例


对于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>
c++智能指针示例


五 自定义删除器

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>
c++智能指针示例


2)

<code>	auto ReleaseData = [](obs_data_t *data)
	{
		obs_data_release(data);
	};
	std::unique_ptr data{
			obs_encoder_defaults(id),
			ReleaseData};/<code>
c++智能指针示例


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>
c++智能指针示例


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>
c++智能指针示例


<code>	std::unique_ptr
		prof_release(static_cast(&ProfilerFree),
				ProfilerFree);/<code>
c++智能指针示例


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>
c++智能指针示例


成员函数中,直接reset() 不用再写具体删除器 就可以了

<code>	formats.reset(ff_format_supported());
	const ff_format_desc *format = formats.get();/<code>
c++智能指针示例

不过如果以列表方式初始化,还要写删除器,如:


<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>
c++智能指针示例



六 自己的例子

<code>
	struct DataDelete {
		void operator() (obs_data_t* d) {
			obs_data_release(d);
		}
	};

	std::unique_ptr pNewSourceSettings;/<code>
c++智能指针示例

<code>			pNewSourceSettings.reset(obs_data_create());
			obs_data_set_int(pNewSourceSettings.get(), "nType", nIndex);/<code>
c++智能指针示例


参考资料:

https://blog.csdn.net/lijinqi1987/article/details/79005794

https://blog.csdn.net/afei__/article/details/80670283


分享到:


相關文章: