避免为非默认参数创建临时变量?
Avoid creating temporary vars for params which are not defaulted?
这听起来可能是一个疯狂的问题。
在我的C++代码中,我创建了一个这样的方法
void Func(int & param_1, bool & param_2, float & param_3, double & param_4) {
//some logic
}
所以我在main
中调用该方法,如下所示:
int i_val;
bool b_val;
float f_val;
double d_val;
//invoke Func here
Func(i_val, b_val, f_val, d_val);
问题:有没有办法避免创建临时变量i_val, b_val, f_val
等等?并在调用本身的行中创建它们?
我只对创造i_val
和b_val
感兴趣,并获得他们的价值。f_val
和d_val
对我来说是不必要的,但在其他一些与我无关的电话中是必要的。有没有办法避免创建临时变量只是为了将每个参数传递到调用中?
我知道我们可以将最后 2个参数作为默认参数,但使用默认参数会使函数参数忽略调用者。有没有办法不使最后 2 个参数默认?在调用方法的那一刻动态创建浮点数和双精度变量
我知道我会得到关于为什么你不想使用默认参数的交叉问题,而只是检查是否有可能:)
当你有四个out 参数时,就像你在这里所做的那样:
void Func(int & param_1, bool & param_2, float & param_3, double & param_4);
这表明您实际上想要返回一个具有 4 个成员的对象,例如:
std::tuple<int, bool, float, double> Func();
或:
struct X {
int some;
bool meaningful;
float names;
double here;
};
X Func();
这样,你就可以写:
auto res = Func();
然后只使用您想要的字段。
在 C++17 中,使用结构化绑定,可以是:
auto [ival, bval, _1, _2] = Func();
没有一种明确的方式来表达你不关心第 3 和第 4 成员的概念,但这还不错。
C++经验法则: 强制引用 当您将某些内容设置为可选时,指针。当然,该函数中的代码需要考虑可以传递的 nullptr。
来得及
void Func(int* pParam_1, bool* pParam_2, float* pParam_3, double* pParam_4) {
// some logic
}
对于像您这样的非const
引用,没有。您可以考虑函数重载,返回包含这些值的struct
,甚至是从 C++11 开始的std::tuple
。(请注意,std::tuple
在 C++14 中得到了重大升级。
如果您将引用设为*const
并依赖返回的值来获取结果,那会让事情变得更好。然后,您可以在调用站点将匿名临时传递给您的函数:
/*something*/ Func(const int& param_1, const bool& param_2, /*etc*/) {
}
并与Func(1, true)
等通话。使用const
引用,您甚至可以提供默认值:
/*something*/ Func(const int& param_1 = 1, const bool& params_2 = true, /*etc*/){
*一些编译器允许将匿名临时绑定到非const
引用作为扩展/无意的错误。但如果我是你,我不会依赖它。
你可以,但你必须知道,假临时会在完整表达式结束时死亡:
template <typename T>
T& stay(T&& x = T()) {
return x;
}
void Func(int& param_1, bool& param_2, float& param_3, double& param_4) {
//some logic
}
int main() {
int arg_1; float arg_3;
Func(arg_1, stay<bool>(), arg_3, stay(42.0));
}
stay
将右值转换为右值,因此与std::move
相反。
调用方法时动态创建浮点数和双精度变量
为此,请使用所需的值创建匿名临时。 然后强制转换它,以便可以绑定到左值引用。
template<class T>
T& as_lvalue(T&& t={}){return t;}
void Func(int& param_1, bool& param_2, float& param_3, double& param_4) {
}
int main() {
int a1;
float a3;
Func(a1, as_lvalue(false), a3, as_lvalue(3.14));
}
as_lvalue
采用右值(或右值!)并将其强制转换为相同类型的左值。 然后,它可以绑定到左值引用,并在表达式末尾丢弃。
如果你不在乎它们的价值是什么,你甚至可以做:
int main() {
int a1;
float a3;
Func(a1, as_lvalue<bool>(), a3, as_lvalue<double>());
}
请注意,使用引用参数作为纯参数有点代码气味。 使用它们时,引用参数应该是自出参数;它们的价值进出应该有用。
携带数据和取出数据的参数也很危险,因为它使得推理函数的行为变得更加困难。
一种非常干净的方法是获取并返回结构。
struct FuncArgs {
int param_1;
bool param_2;
float param_3;
double param_4;
};
FuncArgs Func(FuncArgs) {
//some logic
}
人们可以这样称呼它:
Func({3, true, 42.f, 3.14})
并获取如下返回数据:
auto r = Func({3, true, 42.f, 3.14})
int param1 = r.param1;
bool param2 = r.param2;
忽略返回的param3
和param4
。
在 C++17 中,他们甚至可以做到:
auto[param1, param2, donotcare, alsodonotcare] = Func({3, true, 42.f, 3.14});
可悲的是,没有办法完全跳过donotcare
和alsodonotcare
字段。
但是,如果您的数据是纯粹的结果,我们只是去除FuncArgs
参数。
现在,修改调用Func
的每个位置可能很烦人;但是由于重载的奇迹,我们可以写:
inline FuncArgs Func() {
FuncArgs args;
Func(args.param1, args.param2, args.param3, args.param4);
return args;
}
或
inline FuncArgs Func(FuncArgs args) {
Func(args.param1, args.param2, args.param3, args.param4);
return args;
}
两人幸福地生活在一起。 无需触及现有代码;新代码是。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如果不分配内存,我如何能够为变量创建和分配值?
- 正在头类中为私有变量创建内联函数
- 显示 C++ 中"anonymous"变量创建的警告
- 基于输入变量创建JSON结构
- 使用ROS2环境变量创建C 项目
- 尝试使用自定义类的结构中的变量创建该类的优先级队列
- 为变量创建局部别名会增加开销吗?
- 非静态成员变量创建,如C++中的静态单例创建
- 有没有更好的方法来通过 C/C++ 中的环境变量创建路径
- main () 是使用自动变量创建的,如果是这样,它的目的是什么?
- 我应该用switch语句从变量创建C++模板化对象吗
- 尝试使用值初始化列表,但在使用变量创建大小时不起作用
- 使用变量创建数组
- 为变量创建副本
- <type> 为结构变量创建矢量类型的对象
- 在定义充满成员的结构体时,是否为该结构体类型的每个变量创建这些成员?
- 如何使用要在 cmd 中执行的变量创建命令
- 使用另一个变量创建name变量