【问题标题】:assigning members of a pair to variables将一对成员分配给变量
【发布时间】:2015-08-03 17:02:55
【问题描述】:

是否可以在不创建临时对象的情况下分配对的成员?

#include <tuple>
using namespace std;

pair< bool, int > foo()
{
    return make_pair( false, 3 );
}

int main()
{
    int x;
    bool y;

    auto z = foo();
    x = z.second;
    y = z.first;

    return 0;
}

在上面的代码中,需要 auto z 对象在剖析它之前“持有”该对,但在实际代码中创建它可能代价高昂。

【问题讨论】:

    标签: c++ c++11 c++14


    【解决方案1】:

    是的; std::tie 就是为此而发明的:

    #include <tuple>
    #include <iostream>
    
    std::pair<bool, int> foo()
    {
        return std::make_pair(false, 3);
    }
    
    int main()
    {
        int x;
        bool y;
    
        std::tie(y, x) = foo();
        std::cout << x << ',' << y << '\n';
    }
    
    // Output: 3,0
    

    (live demo)

    当然你仍然会有一个临时对象somewhere(模常数优化),但这是你可以编写的最直接的代码,除非你直接初始化xy从它们的最终值而不是首先在 foo() 中创建一对。

    【讨论】:

    • @jxh 您正在按值返回一个临时值,编译器将已经执行 RVO。 Lightness 指的是(他们是正确的)在std::tie 内,他们必须实例化std::pair 才能提取firstsecond 以分配给您的变量。 std::tie 在这方面只是一个方便的功能。
    • @CoryKramer:RVO 应该意味着tie 的构造函数也可以避免复制。唯一的“副本”应该是由make_pair 创建的副本。
    • 理论上,至少在这种人为的情况下,我希望整个程序只是将30 流式传输到stdout 的几条指令。它可以all被优化掉。如果你的配对更复杂,那么你有 RVO 和移动语义可以依赖。别担心。
    【解决方案2】:

    C++17 已经允许您使用结构化绑定声明语法:

    #include <iostream>
    
    std::pair<bool, int> foo() {
        return std::make_pair(false, 3);
    }
    
    int main() {
        auto [y, x] = foo();               //Structured binding attribution
        std::cout << x << ',' << y << '\n';
    }
    

    【讨论】:

    • 这个小玩意儿的正式名称是structured binding declaration
    • 看来bool y; int x; [y,x] = foo(); 不行。变量必须尚未定义?
    • @Chameleon fool() 是一个返回一对变量(一个 bool 和一个 int)的函数。这是它们的定义。当您编写 auto[y, x] = foo() 时,编译器知道 y 是 bool 而 x 是 int 因为这正是 foo() 返回的内容。
    • @TheArquitect 我明白这一点,但如果 xy 必须已经定义(之前定义,在 ifswitch 内分配),则不起作用。在这种情况下,std::tie 完成了这项工作。
    • @Chameleon 基本上不同之处在于临时创建值并将其归因于(或不归因于)现有变量。这种新格式 auto[x, y] 只是直接创建变量。看到我发现的这个有趣的问题:stackoverflow.com/questions/40241335/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2023-03-04
    • 2016-10-04
    • 1970-01-01
    • 2023-04-08
    • 2021-09-01
    • 2016-06-25
    相关资源
    最近更新 更多