C++ 一个函数的包装器,当我们想要维护调用方状态时,它会修改它的参数

C++ 一个函数的包装器,当我们想要维护调用方状态时,它会修改它的参数,c++,recursion,pass-by-reference,wrapper,out-parameters,C++,Recursion,Pass By Reference,Wrapper,Out Parameters,在函数周围创建一个包装器来修改它的参数(out参数)并且我们想要维护调用方状态,这是一个好的实践吗 有没有更好的方法来实现这一点 下面的示例是一个递归函数,它将在每次递归时修改其参数。我们通过引用来保存副本。问题是,它将修改调用方状态,用户必须考虑这一副作用 // Wrapper to return by value // Example of caller T1 data_1 = ... T2 data_2 = ... T3 result = foo(data_1, data_2); T3

在函数周围创建一个包装器来修改它的参数(out参数)并且我们想要维护调用方状态,这是一个好的实践吗

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

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

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

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

正如您所说的,它更清晰,总体上优化得很好,并且节省了在呼叫站点上声明本地临时值的时间


如果您有一个不能移动或默认构造的类型,您仍然可以使用旧接口

所以,如果我们有可以移动的类型,我们可以简单地使用一个递归函数,使用std::move通过值传递其参数?这不是递归,它只是一个转发重载。是的,如果你现在是从头开始写东西,你可以先按值返回。不过,作为现有代码的包装器,您所拥有的一切都很好。