c++ - 接收参数并为可能失败的函数 move 语义(强大的异常安全性)

标签 c++ c++11 move-semantics idioms exception-safety

我有一个函数可以对作为接收器参数传入的大量数据进行操作。我的 BigData 类型已经支持 C++11,并带有功能齐全的 move 构造函数和 move 赋值实现,因此我无需复制该死的东西就可以逃脱:

Result processBigData(BigData);

[...]

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

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

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

当然,这是行不通的。

由于我我的数据转移到处理函数中,当我到达异常处理程序时,b 将不再可用。

这可能会大大降低我对按值传递接收器参数的热情。

那么问题来了:如何在现代 C++ 代码中处理这种情况?如何检索对先前移入未能执行的函数的数据的访问权限?

您可以根据需要更改 BigDataprocessBigData 的实现和接口(interface)。然而,最终的解决方案应该尽量减少原始代码在效率和可用性方面的缺点。

最佳答案

我同样对这个问题感到困惑。

据我所知,当前最好的习惯用法是将按值传递分成一对按引用传递。

template< typename t >
std::decay_t< t >
val( t && o ) // Given an object, return a new object "val"ue by move or copy
    { return std::forward< t >( o ); }

Result processBigData(BigData && in_rref) {
    // implementation
}

Result processBigData(BigData const & in_cref ) {
    return processBigData( val( in_cref ) );
}

当然,参数的零碎部分可能在异常发生之前就被 move 了。问题传播到任何 processBigData 调用。

我得到了开发一个对象的灵感,它可以在某些异常情况下将自身移回其源头,但这是对我的一个项目中即将出现的特定问题的解决方案。它最终可能会过于特化,或者可能根本不可行。

关于c++ - 接收参数并为可能失败的函数 move 语义(强大的异常安全性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25667284/

相关文章:

c++ - 仿射密码解密,大写和小写输出均不同

c++ - panic : Failed to load dbcapi. dll:

C++11 内存排序——区别?

c++ - 匹配多种类型以进行模板特化解析

c++ - 堆栈可以有一个异常安全的方法来返回和删除具有 move 语义的顶部元素吗?

c++ - 你如何使用映射值?

c++ - 使用 std::array 的代码大小

c++11 - std::forward 的结构

c++ - 赋值运算符的分支与值而不是引用

c++ - move std::thread