当我们想要维护调用者状态时,包装一个修改其参数的函数
Wrapper around a function that modifies its arguments when we want to maintain caller state
围绕修改其参数(输出参数)的函数创建包装器是否是一种好的做法,并且我们希望保持调用者状态?
有没有更好的方法来实现这个?
下面的示例是一个递归函数,它将在每次递归时修改其参数。我们通过引用传递以保存副本。问题是它会修改调用者状态,这种副作用必须由用户考虑。
// Wrapper to return by value
// Example of caller
T1 data_1 = ...
T2 data_2 = ...
T3 result = foo(data_1, data_2);
T3 foo(T1 data_1, T2 data_2) // copy
{
T3 result{};
foo(data_1, data_2, result);
return result;
}
void foo(T1 &data_1, T2 &data_2, T3 &result)
{
// ...
foo(data_1.modify(), data_2.modify(), result);
}
// Alternative, out parameter by reference, will modify data_1 and data_2
// Example of caller
T1 data_1 = ...
T2 data_2 = ...
T3 result{};
foo(data_1, data_2, result);
void foo(T1 &data_1, T2 &data_2, T3 &result)
{
// ...
foo(data_1.modify(), data_2.modify(), result);
}
这很好,如果您在移动语义之前编写了代码,这并不少见,尤其是对于可能在复制省略方面较弱的旧编译器。
正如您所说,它更清晰,通常优化得很好,并且节省了在调用站点声明本地临时对象的时间。
如果您有一个无法移动或默认构造的类型,您仍然可以回退到旧界面。
围绕修改其参数(输出参数)的函数创建包装器是否是一种好的做法,并且我们希望保持调用者状态?
有没有更好的方法来实现这个?
下面的示例是一个递归函数,它将在每次递归时修改其参数。我们通过引用传递以保存副本。问题是它会修改调用者状态,这种副作用必须由用户考虑。
// Wrapper to return by value
// Example of caller
T1 data_1 = ...
T2 data_2 = ...
T3 result = foo(data_1, data_2);
T3 foo(T1 data_1, T2 data_2) // copy
{
T3 result{};
foo(data_1, data_2, result);
return result;
}
void foo(T1 &data_1, T2 &data_2, T3 &result)
{
// ...
foo(data_1.modify(), data_2.modify(), result);
}
// Alternative, out parameter by reference, will modify data_1 and data_2
// Example of caller
T1 data_1 = ...
T2 data_2 = ...
T3 result{};
foo(data_1, data_2, result);
void foo(T1 &data_1, T2 &data_2, T3 &result)
{
// ...
foo(data_1.modify(), data_2.modify(), result);
}
这很好,如果您在移动语义之前编写了代码,这并不少见,尤其是对于可能在复制省略方面较弱的旧编译器。
正如您所说,它更清晰,通常优化得很好,并且节省了在调用站点声明本地临时对象的时间。
如果您有一个无法移动或默认构造的类型,您仍然可以回退到旧界面。