C++ 什么';s是C+中的最短路径+;11(或更新版本)创建RAII包装而不必编写新类?
通常情况下,我需要一个简单的RAII包装器,但由于时间限制和组织问题等原因,我不想为此创建一个全新的类。我的quick-n-dirty解决方案如下 假设我希望确保在作用域结束时,布尔值切换回其原始状态:C++ 什么';s是C+中的最短路径+;11(或更新版本)创建RAII包装而不必编写新类?,c++,c++11,c++14,c++17,raii,C++,C++11,C++14,C++17,Raii,通常情况下,我需要一个简单的RAII包装器,但由于时间限制和组织问题等原因,我不想为此创建一个全新的类。我的quick-n-dirty解决方案如下 假设我希望确保在作用域结束时,布尔值切换回其原始状态: bool prevState = currState; currState = newState; std::unique_ptr<int, std::function<void(int*)>> txEnder(new int(0), [&prevSta
bool prevState = currState;
currState = newState;
std::unique_ptr<int, std::function<void(int*)>> txEnder(new int(0), [&prevState](int* p) {
currState = prevState;
delete p;
});
bool prevState=currState;
currState=newState;
std::unique_ptr txEnder(新int(0),[&prevState](int*p){
currState=prevState;
删除p;
});
此解决方案工作正常,但脏的部分是分配和取消分配该整数的必要性,以便使唯一\u ptr
工作并在销毁时调用自定义析构函数
有没有一种更干净的方法可以做到这一点,而不必编写整个类,并为虚拟int
摆脱new
?您可以使用
比您的要好一点:您可以在自定义析构函数中使用
&prevState
,而无需删除它,因此您无需新建
和删除
某些内容:
void foo(bool & currState, bool newState)
{
bool prevState = currState;
currState = newState;
std::unique_ptr<bool, std::function<void(bool*)>> txEnder(&prevState, [&prevState, &currState](bool* p) {
currState = prevState;
});
cout << "currState: " << currState << endl;
}
void foo(bool&currState,bool newState)
{
布尔状态=当前状态;
currState=newState;
std::unique_ptr txEnder(&prevState,[&prevState,&currState](bool*p){
currState=prevState;
});
不能不要使用std::function
。它会创建很多代码,包括vtables。
如果您绝对不想使用任何外部类或函数,请执行以下操作:
bool foo_2() {
bool f = false;
auto eos = [&](void*){
f = true;
};
std::unique_ptr<void, decltype(eos)> h{&eos,std::move(eos)};
return f;
}
怎么样gsl::finally
?库没有boost那么重,而且finally
不使用std::function
,因此可以轻松地内联。也没有动态分配std::unique\u ptr
using namespace std;
void foo(bool & currState, bool newState)
{
auto revertState = gsl::finally([prevState = currState, &currState]{
currState = prevState;
});
currState = newState;
cout << "currState: " << currState << endl;
}
int main() {
bool state = false;
foo(state, true);
cout << "state: " << state << endl;
return 0;
}
使用名称空间std;
void foo(布尔和柯尔斯塔、布尔新闻州)
{
自动还原状态=gsl::最终([prevState=currState,&currState]{
currState=prevState;
});
currState=newState;
你不能确定你需要分配什么吗?写一个简单的类,在构造时给它一个lambda,然后在析构函数中调用它怎么样?类似于锁守卫。@QuantumPhysica学家我说的不是新类(@πάντα)ῥεῖ 我知道,伙计。我以前在Stackoverflow上讨论过一个(我称之为SmartHandle).但是,再一次,我没有自由在我工作的所有项目中这样做,这取决于许多情况,从匆忙到项目组织问题。@QuantumPhysician如果你因为这样愚蠢的情况而不能做必要的工作,那该有多可惜。但我知道这种情况。这是完美的。我不知道如何做到这一点我没有想到。我只是有点偏执,认为这是否违反了任何规则!这是一个有趣的问题解决方案。我只想指出,这个解决方案可能不是最有效的,因为std::function
应用类型擦除,这意味着动态内存分配(可能是小缓冲区优化)和虚拟函数开销(例如,请参阅)“经典”范围保护,例如来自Boost的范围保护,可能更有效。@量子物理学家还注意到,有人建议添加范围保护(std::scope\…
)进入Stadndard库:。@DanielLangr如果他们在lamdas中添加析构函数,我会更加感激……这将是一个杀手级功能!耶。Boost.:-/你的解决方案可能是正确的,但挑战是要有最短的路径。被接受的答案是超短的,没有任何动态分配。
template<class F>
auto call_at_end_of_scope(F&& f){
auto eos = [f{std::forward<F>(f)}](void*){f();};
return std::unique_ptr<void, decltype(eos)>{&eos,std::move(eos)};
}
bool foo_3() {
bool f = false;
auto handle = call_at_end_of_scope([&](){
f = true;
});
return f;
}
using namespace std;
void foo(bool & currState, bool newState)
{
auto revertState = gsl::finally([prevState = currState, &currState]{
currState = prevState;
});
currState = newState;
cout << "currState: " << currState << endl;
}
int main() {
bool state = false;
foo(state, true);
cout << "state: " << state << endl;
return 0;
}