结合Linux平台RTSP|RTMP播放器demo谈谈std::remove_if

背景

好多开发者可能会疑惑,你一个搞音视频开发的,怎么做起了C++基础普及的事情?搞音视频底层开发的,大多需要有相对好的C C++基础,这里提到的std::remove_if,也是因为大牛直播SDK的demo代码里面有用到。有些对接的开发者容易疑惑,做个基础的扫盲。

以我们Linux平台RTSP|RTMP多路播放的demo为例,我们针对event handler做了封装,大概的设计如下:

/*
 * nt_sdk_handle_wrapper.h
 * Created by daniusdk.com (C) All rights reserved.
 */
class NT_SDK_HandleWrapper
{
public:
	explicit NT_SDK_HandleWrapper(SmartPlayerSDKAPI* sdk_api);
	~NT_SDK_HandleWrapper();

public:
	void AddEventHandler(const std::shared_ptr<NT_SDK_EventHandler>& handler);
	void RemoveHandler(const std::shared_ptr<NT_SDK_EventHandler>& handler);
	void RemoveHandler(const NT_SDK_EventHandler* handler);

    ...

private:
	std::recursive_mutex event_handlers_mutex_;
	std::vector<std::weak_ptr<NT_SDK_EventHandler> > event_handlers_;
};

其他不再赘述,针对AddEventHandler()和RemoveHandler()处理如下:

void NT_SDK_HandleWrapper::AddEventHandler(const std::shared_ptr<NT_SDK_EventHandler>& handler)
{
	assert(handler);

	std::unique_lock<std::recursive_mutex> lock(event_handlers_mutex_);

	auto iter = std::find_if(begin(event_handlers_), end(event_handlers_),
		[&handler](const std::weak_ptr<NT_SDK_EventHandler>& i)->bool
	{
		if (i.lock() == handler)
		{
			return true;
		}

		return false;
	});


	if (iter == end(event_handlers_))
	{
		event_handlers_.push_back(handler);
	}
}

void NT_SDK_HandleWrapper::RemoveHandler(const std::shared_ptr<NT_SDK_EventHandler>& handler)
{
	assert(handler);

	std::unique_lock<std::recursive_mutex> lock(event_handlers_mutex_);

	auto iter = std::remove_if(begin(event_handlers_), end(event_handlers_),
		[&handler](const std::weak_ptr<NT_SDK_EventHandler>& i)->bool
	{
		if (i.lock() == handler)
		{
			return true;
		}

		return false;
	}
	);

	if (iter != end(event_handlers_))
	{
		event_handlers_.erase(iter, end(event_handlers_));
	}
}

void NT_SDK_HandleWrapper::RemoveHandler(const NT_SDK_EventHandler* handler)
{
	assert(handler != nullptr);

	std::unique_lock<std::recursive_mutex> lock(event_handlers_mutex_);

	auto iter = std::remove_if(begin(event_handlers_), end(event_handlers_),
		[&handler](const std::weak_ptr<NT_SDK_EventHandler>& i)->bool
	{
		auto obj = i.lock();
		if (!obj)
		{
			return true;
		}

		if (obj.get() == handler)
		{
			return true;
		}

		return false;
	}
	);

	if (iter != end(event_handlers_))
	{
		event_handlers_.erase(iter, end(event_handlers_));
	}
}

std::remove_if扫盲

这里部分开发者可能会有疑惑,std::remove_if 是 C++ 标准库中的一个算法函数,定义在 <algorithm> 头文件中。它的主要功能是根据用户提供的条件,将容器中满足该条件的元素移除。

std::remove_if 的函数签名如下:

template< class ForwardIt, class UnaryPredicate >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPredicate p );

参数解释

  • first 和 last:表示容器中元素范围的迭代器,[first, last) 是要操作的元素范围。
  • p:一个一元谓词函数,接受一个参数,其返回值是 bool 类型。该谓词函数会对 [first, last) 范围内的元素进行判断,返回 true 表示该元素应该被移除。

工作原理

  • std::remove_if 并不会真正从容器中删除元素,因为它没有办法改变容器的大小。实际上,它会将不需要移除的元素移动到容器的前面,并返回一个新的 “逻辑结束” 迭代器,该迭代器指向最后一个不需要移除元素的下一个位置。
  • 为了真正删除元素,你需要结合容器的 erase 成员函数,使用 erase-remove_if 惯用法。

总结

  • std::remove_if 适用于顺序容器,如 vectorlistdeque 等。
  • 对于关联容器(如 setmap),由于它们有自己的删除元素的成员函数,并且元素存储是有序的,不应该使用 std::remove_if
  • 在使用 erase-remove_if 惯用法时,要确保容器支持 erase 操作。

通过这种方式,你可以方便地根据自定义条件从容器中移除元素,并且代码简洁高效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值