存在错误代码时的输出参数与 NRVO
Out params vs. NRVO in the presence of error codes
我们有一个广泛使用 out 参数的代码库,因为每个函数都可能因某些错误枚举而失败。
这变得非常混乱,代码有时无法阅读。
我想消除这种模式并采用更现代的方法。
目标是改造:
error_t fn(param_t *out) {
//filling 'out'
}
param_t param;
error_t err = fn(¶m);
变成类似这样的东西:
std::expected<error_t, param_t> fn() {
param_t ret;
//filling 'ret'
return ret;
}
auto& [err, param] = fn();
以下问题是为了说服自己和其他人这个改变是最好的:
- 我知道在标准级别上,NRVO 不是强制性的(与 c++17 中的 RVO 不同)但实际上它是否有可能不会在任何主要编译器中发生?
- 使用 out 参数代替 NRVO 有什么优势吗?
- 假设 NRVO 发生,生成的程序集是否有重大变化(假设优化的
expected
实现 [可能表示错误发生的布尔值完全消失])?
首先,一些假设:
我们正在查看未内联的函数。在那种情况下几乎可以保证是绝对等价的。
我们假设函数的调用点在使用返回值之前实际检查了错误条件。
我们假设返回值没有用部分数据预初始化。
我们假设我们只关心优化代码。
正在成立:
I know that on the standard level, NRVO is not mandatory (unlike RVO in c++17) but practically is there any chance it won't happen in any of the major compilers?
假设此时正在执行 NRVO 是一个安全的赌注。我敢肯定有人会想出一个不会发生的人为情况,但我通常相信在几乎所有用例中,NRVO 都是在当前的现代编译器上执行的。
话虽如此,我绝不会依赖此行为来保证程序 正确性 。 IE。我不会制作一个带有副作用的奇怪复制构造函数,假设它不会因 NRVO 而被调用。
Are there any advantages of using out parameters instead of NRVO?
通常不会,但就像 C++ 中的所有内容一样,在某些边缘情况下可能会出现。用于最大化缓存一致性的显式内存布局将是 "returning by pointer".
的一个很好的用例
Assuming NRVO happens, is there a a significant change in the generated assembly (assuming an optimized expected implementation [perhaps with the boolean representing whether an error occured completly disappear])?
这个问题对我来说意义不大。 expected<>
比 tuple<>
更像 variant<>
,所以 "boolean representing whether an error occured completly disappear" 没有意义。
话虽这么说,我想我们可以用std::variant来估计:
它是 "different",但在我看来不一定更好或更坏。
我们有一个广泛使用 out 参数的代码库,因为每个函数都可能因某些错误枚举而失败。 这变得非常混乱,代码有时无法阅读。
我想消除这种模式并采用更现代的方法。
目标是改造:
error_t fn(param_t *out) {
//filling 'out'
}
param_t param;
error_t err = fn(¶m);
变成类似这样的东西:
std::expected<error_t, param_t> fn() {
param_t ret;
//filling 'ret'
return ret;
}
auto& [err, param] = fn();
以下问题是为了说服自己和其他人这个改变是最好的:
- 我知道在标准级别上,NRVO 不是强制性的(与 c++17 中的 RVO 不同)但实际上它是否有可能不会在任何主要编译器中发生?
- 使用 out 参数代替 NRVO 有什么优势吗?
- 假设 NRVO 发生,生成的程序集是否有重大变化(假设优化的
expected
实现 [可能表示错误发生的布尔值完全消失])?
首先,一些假设:
我们正在查看未内联的函数。在那种情况下几乎可以保证是绝对等价的。
我们假设函数的调用点在使用返回值之前实际检查了错误条件。
我们假设返回值没有用部分数据预初始化。
我们假设我们只关心优化代码。
正在成立:
I know that on the standard level, NRVO is not mandatory (unlike RVO in c++17) but practically is there any chance it won't happen in any of the major compilers?
假设此时正在执行 NRVO 是一个安全的赌注。我敢肯定有人会想出一个不会发生的人为情况,但我通常相信在几乎所有用例中,NRVO 都是在当前的现代编译器上执行的。
话虽如此,我绝不会依赖此行为来保证程序 正确性 。 IE。我不会制作一个带有副作用的奇怪复制构造函数,假设它不会因 NRVO 而被调用。
Are there any advantages of using out parameters instead of NRVO?
通常不会,但就像 C++ 中的所有内容一样,在某些边缘情况下可能会出现。用于最大化缓存一致性的显式内存布局将是 "returning by pointer".
的一个很好的用例Assuming NRVO happens, is there a a significant change in the generated assembly (assuming an optimized expected implementation [perhaps with the boolean representing whether an error occured completly disappear])?
这个问题对我来说意义不大。 expected<>
比 tuple<>
更像 variant<>
,所以 "boolean representing whether an error occured completly disappear" 没有意义。
话虽这么说,我想我们可以用std::variant来估计:
它是 "different",但在我看来不一定更好或更坏。