[英]Changing variable names in the middle of a function
假设我有一些具有初始名称的对象,例如quantities_of_widgets
。
std::vector<int> quantities_of_widgets = GetQuantities();
然后我就地对quantities_of_widgets
执行操作。 向量quantities_of_widgets
不再表示“称为小部件的某些数量的向量”。
PerformOperationInPlace(quantities_of_widgets);
在此操作之后,更合适的变量名称是weights_of_widgets
。 这肯定会使代码更具可读性。
我可以通过移动“改变”这个名字quantities_of_widgets
到一个新的载体weights_of_widgets
。 这是一个可怕的想法。 移动不是免费的,它会干扰内存连续性等。
std::vector<int> weights_of_widgets = std::move(quantities_of_widgets);
我还可以在注释中记录变量的含义。 我可能会写
std::vector<int> widgets = GetQuantities(); // widgets represents quantities
PerformOperationInPlace(widgets); // widgets represents weights
UseWeights(widgets);
但是,注释的永久性和可读性较差。 在多行代码中跟踪变量的含义变得更加困难。 如果在大表达式中间向下 20 行使用widgets
,我将无法记录此时变量的含义。
SomeBigFunction(Func1(widgets, some_other_object_1), some_other_object_2);
我可以尝试别名,但我想让旧名称无效以帮助维护。 有没有办法在没有运行时成本的情况下更改变量的名称?
除了最极端的情况外,担心如此小的开销几乎肯定不值得付出努力。 但是,为了完整起见:
使用非平凡析构函数获得真正无开销的类型重命名的唯一方法是通过复制省略。
在这种情况下,您可以通过立即评估的 lambda 和 NRVO 来使用它。
#include <vector>
std::vector<int> GetQuantities(int v);
void PerformOperationInPlace(std::vector<int>&);
void UseWeights(const std::vector<int>&);
template<typename T>
T rename(T&& rhs) {
return rhs;
}
void foo(int x) {
std::vector<int> quantities_of_widgets = GetQuantities(x);
PerformOperationInPlace(quantities_of_widgets);
UseWeights(quantities_of_widgets);
}
void bar(int x) {
std::vector<int> weights_of_widgets = [&]{
std::vector<int> quantities_of_widgets = GetQuantities(x);
PerformOperationInPlace(quantities_of_widgets);
return quantities_of_widgets;
}();
UseWeights(weights_of_widgets);
}
foo()
和bar()
编译为有效的完全相同的最终程序集:(参见Godbolt )
唯一的限制是要重命名的变量必须在 lambda 中声明。 除此之外,通过引用隐式捕获使 lambda 有效地与作用域相同。
最好自己记录代码。 评论有降低的趋势。 所以我会这样做:
// name of this function terrible, it should be more like
// ExtractWeightsOfWidgetsFrom or something similar
std::vector<int> OperationInPlace(std::vector<int> data) {
// note argument is a copy!
....
return data;
}
void someCode() {
auto quantities_of_widgets = GetQuantities();
...
auto weights_of_widgets = PerformOperationInPlace(std::move(quantities_of_widgets));
// here `quantities_of_widgets` is empty since contents has been moved
// many tools will report an error if you use this value after that point
....
}
或者更好的是,我只想提取更多功能:
void someCode() {
auto quantities_of_widgets = GetQuantities();
...
ProcesWeightsOfWidgets(
PerformOperationInPlace(std::move(quantities_of_widgets));
// in this version someCode ends here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.