简体   繁体   English

在函数中间更改变量名

[英]Changing variable names in the middle of a function

Suppose I have some object with an initial name such as quantities_of_widgets .假设我有一些具有初始名称的对象,例如quantities_of_widgets

std::vector<int> quantities_of_widgets = GetQuantities();

I then perform an operation on quantities_of_widgets in-place.然后我就地对quantities_of_widgets执行操作。 The vector quantities_of_widgets no longer represents "a vector of some quantities of things called widgets".向量quantities_of_widgets不再表示“称为小部件的某些数量的向量”。

PerformOperationInPlace(quantities_of_widgets);

After this operation, a more appropriate name for the variable would be weights_of_widgets .在此操作之后,更合适的变量名称是weights_of_widgets That would certainly make the code more readable.这肯定会使代码更具可读性。

I can "change" the name by moving quantities_of_widgets to a new vector weights_of_widgets .我可以通过移动“改变”这个名字quantities_of_widgets到一个新的载体weights_of_widgets This is a terrible idea.这是一个可怕的想法。 The move isn't free, it messes with memory continuity, etc.移动不是免费的,它会干扰内存连续性等。

std::vector<int> weights_of_widgets = std::move(quantities_of_widgets);

I could also document the meaning of the variable in comments.我还可以在注释中记录变量的含义。 I might write我可能会写

std::vector<int> widgets = GetQuantities(); // widgets represents quantities
PerformOperationInPlace(widgets); // widgets represents weights
UseWeights(widgets);

However, comments are less permanent and less readable.但是,注释的永久性和可读性较差。 It becomes more difficult to keep track of the meaning of variables over multiple lines of code.在多行代码中跟踪变量的含义变得更加困难。 If widgets is used 20 lines down in the middle of a large expression, I'd have trouble documenting the meaning of the variable at that point.如果在大表达式中间向下 20 行使用widgets ,我将无法记录此时变量的含义。

SomeBigFunction(Func1(widgets, some_other_object_1), some_other_object_2);

I could try aliasing, but I want to make the old name invalid to help with maintainability.我可以尝试别名,但我想让旧名称无效以帮助维护。 Is there a way to change the name of a variable with no run-time cost?有没有办法在没有运行时成本的情况下更改变量的名称?

Worrying about such small overhead is almost certainly not worth the effort in all but the most extreme scenarios.除了最极端的情况外,担心如此小的开销几乎肯定不值得付出努力。 However, for the sake of completeness:但是,为了完整起见:

The only way to get truly overhead-free renaming of types with non-trivial destructors is via copy-elision.使用非平凡析构函数获得真正无开销的类型重命名的唯一方法是通过复制省略。

In this context, you could make use of it via an immediately evaluated lambda and NRVO.在这种情况下,您可以通过立即评估的 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() and bar() compile down to effectively the exact same final assembly: (see on godbolt ) foo()bar()编译为有效的完全相同的最终程序集:(参见Godbolt

The only limitation is that the variable that will be renamed has to be declared within the lambda.唯一的限制是要重命名的变量必须在 lambda 中声明。 Beyond that, implicit capture by reference makes the lambda effectively the same thing as a scope.除此之外,通过引用隐式捕获使 lambda 有效地与作用域相同。

It is best to document code by itself.最好自己记录代码。 Comments have tendency do degrade.评论有降低的趋势。 So I would do this this way:所以我会这样做:

// 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
    ....
} 

or even better I would just extract more functions:或者更好的是,我只想提取更多功能:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM