c++引用无效
C++ Reference invalidation
我正在为游戏引擎编写一个事件系统,我需要一种从事件中"断开"函数的方法(从std::vector中删除),但我也要求删除事件时开发者必须给出他们希望断开的函数的有效引用。
现在我有一个这样的类:
template<typename ... Args>
class event{
public:
using delegate_type = std::function<void(Args...)>;
void operator()(Args ... args){
for(auto &&f : m_funcs)
f(args...);
}
template<typename FunctorType>
delegate_type &connect(FunctorType &&f){
m_funcs.emplace_back(f);
return m_funcs.back();
}
bool disconnect(delegate_type &f){
for(auto iter = begin(m_funcs); iter != end(m_funcs); ++iter)
if(&(*iter) == &f){ // if the dev passed a valid function
m_funcs.erase(iter);
return true;
}
return false;
}
private:
std::vector<delegate_type> m_funcs;
};
但是,当在disconnect
或connect
操作后调整底层向量的大小时,这当然会受到引用无效的影响。
我尝试切换到std::list
解决方案,而不是std::vector
,但迭代函数时的速度差异是有害的,我不能在发布构建中切换。
是否有一些方法可以避免使用helper类或标识符而不是直接引用的无效?
我建议你看一下Boost.Signals2。当连接时,它返回一个sigc::connection
对象。您可以将其保持在客户端并使用它来断开连接,或者它将在插槽被破坏时自动断开连接。它不会受到引用无效问题的困扰。
存储weak_ptr<delegate_type>
。在每次调用时删除无效的(remove_if
)。( operator()
)。以某种方式防止递归调用。
返回shared_ptr<delegate_type>
作为令牌。外部用户只需使用.reset()
取消注册。无需disconnect
!
在connect
中分配make_shared<delegate_type>
。
使connect
成为template
,完美地向前进入make_shared
。
使用一个关联容器,就像刚才使用的std::list。
但是,您需要更复杂地使用容器,以便消除循环的开销。
最好的解决方案当然是去掉循环。
最有效的方法是返回容器单元格的迭代器,而不是返回函数本身。
这样的移除可以避免搜索,因为你已经有了迭代器的位置。
在关联容器中,迭代器不会失效(但要注意,这当然不是线程安全的)。
template<typename FunctorType>
std::list<delegate_type>::iterator &connect(FunctorType &&f){
m_funcs.emplace_back(f);
//get the iterator for the last item
return m_funcs.end()--;
}
bool disconnect(std::list<delegate_type>::iterator &f){
//direct removal
m_funcs.erase(f);
return true;
}
- C++-模板嵌套类的引用初始化无效
- 在这个函数中是有缺陷的,因为取消引用 null 是无效的,所以我想更改代码
- 从 BubbleSort* 类型的右值初始化 'AssortedSorter&' 类型的非常量引用无效"
- 为什么在引用指针时将 const 放在 & 符号的左侧有效,而在右侧则无效?
- 为什么通过 vector<reference_wrapper> 的元素删除引用的值<T>不会使向量无效?
- 具有引用返回类型的重写方法上的协变返回类型无效
- 为什么我总是收到此错误:从类型为"农场动物"的右值初始化类型的非常量引用无效|
- 对全局变量的非常量引用的初始化无效
- 为什么右值不能绑定到非常量左值引用,除了写入临时无效的事实?
- 对类型为 std::_Bit_rerefence& 的非常量引用的初始化无效
- 模板流运算符重载错误:引用初始化无效,与basic_istream和basic_ifstream之间的差异有关
- 成本字符*类型的非常量引用的无效初始化,并且来自常量字符*类型的临时引用
- 对唯一 ptr 无效读取的引用向量
- 中毒的无效引用和短路表达评估错误或UB
- 返回无效引用
- 在基于范围的 for 循环中获取无效引用
- 通过重新解释强制转换创建无效引用
- 子弹物理由于无效引用而崩溃
- 对多态对象成员的无效引用
- 基于jobobject调用Java方法失败(无效引用?)