gpt4 book ai didi

c++ - 正确使用通用引用

转载 作者:可可西里 更新时间:2023-11-01 18:20:05 25 4
gpt4 key购买 nike

在c++11之前,我曾经这样写代码:

// Small functions
void doThingsWithA(const A& a)
{
// do stuff
}

void doThingsWithB(const B& b)
{
// do stuff
}

void doThingsWithC(const C& c)
{
// do stuff
}

// Big function
void doThingsWithABC(const A& a, const B& b, const C& c)
{
// do stuff
doThingsWithA(a);
doThingsWithB(b);
doThingsWithC(c);
// do stuff
}

但是现在,有了移动语义,允许我的函数将右值引用作为参数并添加这些重载可能会变得有趣(至少在某些情况下):

void doThingsWithA(A&& a);
void doThingsWithB(B&& b);
void doThingsWithC(C&& c);

据我所知,如果我希望能够在我的大函数中调用那些重载,我需要使用完美转发,它可能看起来像这样(它的可读性有点差,但我想它可以好的模板类型的命名约定):

template<typename TplA, typename TplB, typename TplC>
void doThingsWithABC(TplA&& a, TplB&& b, TplC&& c)
{
// do stuff
doThingsWithA(std::forward<TplA>(a));
doThingsWithB(std::forward<TplB>(b));
doThingsWithC(std::forward<TplC>(c));
// do stuff
}

我的问题是:这是否意味着如果我的小函数有其他重载,就可以使用非预期类型的​​参数调用大函数?

我认为这可能有助于防止这种情况:

template<typename TplA, typename TplB, typename TplC,
class = typename std::enable_if<std::is_same<A, std::decay<TplA>::type>::value>::type,
class = typename std::enable_if<std::is_same<B, std::decay<TplB>::type>::value>::type,
class = typename std::enable_if<std::is_same<C, std::decay<TplC>::type>::value>::type>
doThingsWithABC(TplA&& a, TplB&& b, TplC&& c)
{
// do stuff
doThingsWithA(std::forward<TplA>(a));
doThingsWithB(std::forward<TplB>(b));
doThingsWithC(std::forward<TplC>(c));
// do stuff
}

虽然我不确定它是否没有太多限制,因为我不知道如果我尝试调用具有可隐式转换为 A、B 或 C 的类型的大函数,它会如何表现...

但是......即使假设这可行,我真的没有其他选择吗? (我的意思是......这对眼睛来说并不容易)

最佳答案

完美转发主要用于当您不知道数据将如何被使用时,因为您正在编写“用户提供”数据的通用包装器。

在您上面描述的简单程序系统中,您所做的 3 件事将是具体任务。

这意味着您将知道他们是否会从拥有可移动的数据源中受益,如果他们必须复制它们是否有意义,以及移动是否便宜。

如果复制有意义,但移动速度更快,并且移动成本低(常见情况),则他们应该按值获取参数,并在存储本地拷贝时将其移出。

此规则然后递归地应用于调用 3 个子函数的函数。

如果函数不能从移动中获益,则使用const&

如果复制没有意义,按右值引用(不是通用引用)或按值获取。

在能够move move 都很好的情况下,如果您考虑完美转发,move 仍然很昂贵。如上所述,这通常仅在包装代码库的“用户”设置的函数时发生,因为通常 move 要么非常便宜,要么像复制一样昂贵。您必须处于 move 效率的中间或不确定阶段,完美转发才有值(value)。

完美转发还有其他用途,例如容器修改器,但它们更加深奥。例如,我的 backwards range mutator 会将传入的范围完美地转发到存储中,以便在您以 C++11 样式的基于范围的 链接多个范围 mutator 时使引用生命周期延长正常工作for(:) 循环。

疯狂完美的转发会导致生成的代码膨胀、构建缓慢、实现漏洞和代码难以理解。

关于c++ - 正确使用通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24296951/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com