我们假设我有三个函数f0, f1, f2
,它们都有三个参数。我们还假设我有一个很大的函数bigFunc
来调用,它将前三个函数的返回值作为参数。
我可能想打这样的电话:
bigFunc(f0(arg0, arg1, arg2), f1(arg3, arg4, arg5), f2(arg6, arg7, arg8));
这是一个很大的调用,所以我认为写这样的东西会更具可读性:
auto bigArg0 = f0(arg0, arg1, arg2);
auto bigArg1 = f1(arg3, arg4, arg5);
auto bigArg2 = f2(arg6, arg7, arg8);
bigFunc(bigArg0, bigArg1, bigArg2);
如果名称bigArg0, bigArg1, bigArg2
允许我更具体地说明我正在做什么(例如,如果f0, f1, f2
有点通用;那么你可以想到STL算法,那就特别棒了根据你给它的迭代器类型,它会做不同的事情。)
然而,问题在于,通过命名bigArg0, bigArg1, bigArg2
,我不再使它们成为临时工,这(我认为)编译器难以优化。
所以,这是我的问题:如果我不想失去性能,那么正确的方法是什么? make bigArg0, bigArg1, bigArg2
const?将参数提供给bigFunc
到std::move
?两者兼而有之?
答案 0 :(得分:3)
返回值的析构函数和复制构造函数是否具有可观察的行为,因为标准定义了它们?
如果他们不这样做并且编译器具有证明它的所有必要信息,编译器可以在不需要RVO异常的情况下隐藏副本。
如果你使用std::move
,也许就是这种情况?无论哪种方式移动都可能比复制更好......
或许bigfunc
通过常量引用获取其参数,在这种情况下,两种方式都会产生相同的代码......
答案 1 :(得分:1)
这是一个避免命名时间的解决方案:
bigFunc(
f0(arg0, arg1, arg2),
f1(arg3, arg4, arg5),
f2(arg6, arg7, arg8)
);
放大的例子:
bigFunc(
f0(
f0_0(arg0, arg1, arg2),
f0_1(arg3, arg4, arg5),
f0_2(arg6, arg7, arg8)
),
f1(
f1_0(arg9, arg10, arg11),
f1_1(arg12, arg13, arg14),
f1_2(arg15, arg16, arg17)
),
f2(
f2_0(arg18, arg19, arg20),
f2_1(arg21, arg22, arg23),
f2_2(arg24, arg25, arg26)
)
);
它在17条易于阅读的行中处理27个参数和13个函数调用。
在一个地方已经做了很多事情。到目前为止,它的扩展到它失去了可读性时,你应该开始将它的一部分放入单独的函数中和/或将参数组合成结构或类。