为可能失败的函数(强异常安全)接收参数和移动语义 [英] Sink arguments and move semantics for functions that can fail (strong exception safety)

查看:196
本文介绍了为可能失败的函数(强异常安全)接收参数和移动语义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,对作为sink参数传入的大块数据进行操作。我的 BigData 类型已经是C ++ 11感知的,并且具有完全功能的移动构造函数和移动赋值实现,所以我可以离开,而不必复制的东西: / p>

 结果processBigData(BigData); 

[...]

BigData b = retrieveData();
结果r = processBigData(std :: move(b));

这一切都很好。但是,我的处理函数可能会偶尔在运行时失败,导致异常。这不是一个真正的问题,因为我只能修复的东西,并重试:

  BigData b = retrieveData 
结果r;
try {
r = processBigData(std :: move(b));
} catch(std :: runtime_error&){
r = fixEnvironmnentAndTryAgain(b);
//等等,有些不对了...
}

当然,这不会工作。



由于我将数据移入处理函数,在我到达异常时



这可能会大大降低我对传递sink参数的热情。值。



这里是一个问题:如何在现代C ++代码中处理这种情况?



您可以更改 BigData

的实现和接口, / code>和 processBigData 。然而,最终的解决方案应该尝试最小化关于效率和可用性的原始代码的缺点。

解决方案

显然,最近的CppCon 2014. Herb Sutter在他的闭幕词中总结了最新的状态,



他的结论很简单:不要使用pass-by-value



首先使用这种技术的参数(正如Eric Niebler的Meeting C ++ 2013主题一般推广 C ++ 11图书馆设计(投影片) )似乎超过了缺点。传递sink参数by-value的初始动机是去掉使用 const& / &&& ;



不幸的是,这似乎带来了一些意想不到的结果。其中之一是潜在的效率缺点(主要是由于不必要的缓冲区分配)。另一个是从这个问题的异常安全的问题。



Herb的结论是不是使用pass-by-value作为sink参数,而是依赖于分隔 const& / &&& (with const& 为默认值,&&& 为需要优化的少数情况保留)。



Potatoswatter的回答建议的匹配。通过传递sink参数通过&&& 我们可能可以推迟实际移动的数据从参数到一个点,我们可以给出noexcept保证。 / p>

我喜欢传递sink参数by-value的想法,但似乎它在实践中并不像每个人都希望的那样。


I have a function that operates on a big chunk of data passed in as a sink argument. My BigData type is already C++11-aware and comes with fully functional move constructor and move assignment implementations, so I can get away without having to copy the damn thing:

Result processBigData(BigData);

[...]

BigData b = retrieveData();
Result r = processBigData(std::move(b));

This all works perfectly fine. However, my processing function may fail occasionally at runtime resulting in an exception. This is not really a problem, since I can just fix stuff and retry:

BigData b = retrieveData();
Result r;
try {
    r = processBigData(std::move(b));
} catch(std::runtime_error&) {
    r = fixEnvironmnentAndTryAgain(b);
    // wait, something isn't right here...
}

Of course, this won't work.

Since I moved my data into the processing function, by the time I arrive in the exception handler, b will not be usable anymore.

This threatens to drastically reduce my enthusiasm for passing sink arguments by-value.

So here is the question: How to deal with a situation like this in modern C++ code? How to retrieve access to data that was previously moved into a function that failed to execute?

You may change the implementation and interfaces for both BigData and processBigData as you please. The final solution however should try to minimize drawbacks over the original code regarding efficiency and usability.

解决方案

Apparently this issue was discussed lively at the recent CppCon 2014. Herb Sutter summarized the latest state of things in his closing talk, Back to the Basics! Essentials of Modern C++ Style (slides).

His conclusion is quite simply: Don't use pass-by-value for sink arguments.

The arguments for using this technique in the first place (as popularized by Eric Niebler's Meeting C++ 2013 keynote C++11 Library design (slides)) seem to be outweighed by the disadvantages. The initial motivation for passing sink arguments by-value was to get rid of the combinatorial explosion for function overloads that results from using const&/&&.

Unfortunately, it seems that this brings a number of unintended consequences. One of which are potential efficiency drawbacks (mainly due to unnecessary buffer allocations). The other is the problem with exception safety from this question. Both of these are discussed in Herb's talk.

Herb's conclusion is to not use pass-by-value for sink arguments, but instead rely on separate const&/&& (with const& being the default and && reserved for those few cases where optimization is required).

This also matches with what @Potatoswatter's answer suggested. By passing the sink argument via && we might be able to defer the actual moving of the data from the argument to a point where we can give a noexcept guarantee.

I kind of liked the idea of passing sink arguments by-value, but it seems that it does not hold up as well in practice as everyone hoped.

这篇关于为可能失败的函数(强异常安全)接收参数和移动语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆