【问题标题】:Wrapper around a function that modifies its arguments when we want to maintain caller state当我们想要维护调用者状态时,包装一个修改其参数的函数
【发布时间】:2019-01-03 18:46:30
【问题描述】:

为修改其参数(输出参数)的函数创建一个包装器并且我们希望保持调用者状态是一种好习惯吗?

有没有更好的方法来实现这一点?

以下示例是一个递归函数,它将在每次递归时修改其参数。我们通过引用来保存副本。问题是它会修改调用者状态,这个副作用必须由用户考虑。

// 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);
}

【问题讨论】:

    标签: c++ recursion pass-by-reference wrapper out-parameters


    【解决方案1】:

    如果您在移动语义之前编写了代码,这很好,而且并不少见,尤其是对于复制省略可能较弱的旧编译器。

    正如您所说,它更清晰,通常优化得很好,并且可以节省在调用站点声明本地临时对象。

    如果您有一个无法移动或默认构造的类型,您仍然可以使用旧界面。

    【讨论】:

    • 因此,如果我们有可以移动的类型,我们可以简单地使用一个递归函数,使用 std::move 按值传递其参数?
    • 这不是递归,它只是转发过载。是的,如果你现在从头开始写东西,你可以一开始就按值返回。不过,您所拥有的可以作为现有代码的包装器。
    猜你喜欢
    • 2019-01-21
    • 2022-01-05
    • 1970-01-01
    • 2016-10-18
    • 2010-10-09
    • 1970-01-01
    • 2018-05-23
    相关资源
    最近更新 更多