当前位置: 首页 > 知识库问答 >
问题:

基于无序_图和参考的循环范围[重复]

龙弘济
2023-03-14

在std::unordered_映射上运行基于范围的for循环时,循环变量的类型似乎不使用引用类型:

std::unordered_map<int, int> map = { {0, 1}, {1, 2}, {2, 3} };
for(auto&[l, r] : map)
    static_assert(std::is_same_v<decltype(r), int&>);

MSVC 2017、gcc 8.2和clang 7.0.0都在这里报告了一个失败的断言。与std::vector相反,它的断言不会失败,正如人们所期望的那样:

std::vector<int> vec = { 1, 2, 3 };
for(auto& r : vec)
    static_assert(std::is_same_v<decltype(r), int&>);

然而,在MSVC 2017和gcc 8.2上,修改局部变量r的循环将产生明显的副作用:

#include <iostream>
#include <type_traits>
#include <unordered_map>
#include <vector>

int main() {
    std::unordered_map<int, int> a = { {0, 1}, {1, 2}, {2, 3} };
    for(auto[l, r] : a)
        std::cout << l << "; " << r << std::endl;
    for(auto&[l, r] : a) {
        static_assert(std::is_same_v<decltype(r), int>);
        r++;
    }
    std::cout << "Increment:" << std::endl;
    for(auto[l, r] : a)
        std::cout << l << "; " << r << std::endl;
}

例如,此程序将打印(忽略订单):

0; 1
1; 2
2; 3
Increment:
0; 2
1; 3
2; 4

我遗漏了什么?尽管局部变量不是引用类型,但这如何改变映射中的值?或者更恰当地说,为什么std::is_same看不到正确的类型,因为很明显它是引用类型?或者我是否遗漏了一些未定义的行为?

请注意,我没有使用结构化绑定来重现相同的问题,所以我在这里保留了漂亮的代码

共有1个答案

安博文
2023-03-14

结构化绑定被建模为别名,而不是“真实”引用。即使他们可能在幕后使用引用。

想象一下你有

struct X {
    const int first = 0;
    int second;
    int third : 8;
};

X x;
X& y = x;

什么是decltype(x.second)<代码>整数。什么是decltype(y.second)<代码>整数。所以在

auto& [first, second, third] = x;

decltype(second)int,因为secondx.second的别名。而third即使不允许将引用绑定到位字段,也不会带来任何问题,因为它是一个别名,而不是实际引用。

类似于tuple的case就是为了与此保持一致而设计的。即使在这种情况下,语言必须使用引用,它也会尽力假装这些引用不存在。

 类似资料:
  • 由于valgrind中出现了一些分段错误和警告,我发现这段代码不正确,并且在for range循环中有一些悬而未决的引用。 看起来好像开始和结束是从一个临时循环中提取的,并且在循环中丢失了。 当然,一种方法是 然而,我想知道为什么for(auto e:f()[5])是一个错误,以及是否有更好的方法或某种方法来设计f,甚至容器(

  • 我对C很陌生,现在就在做中学习。在课堂材料中,我有以下功能: 几分钟前,我像这样使用了普通for循环:

  • 在处理指针向量时,我偶然发现了一个奇怪的bug: mwe.cpp代码: 如何复制: (ARCH上的GCC 9.2.0也复制了这个Bug,但Apple clang 11.0.0给出了预期的输出) 预期产出: 实际产量: 我是否无意中在某处引入了未定义行为?如果没有,为什么这没有按预期工作?

  • 在临时范围上基于范围的for循环中,Barry提到以下内容不受被破坏的临时对象的影响,我测试的成员v确实存在于for循环的整个循环中(因为在for循环的整个循环中没有调用析构函数X)。解释是什么?

  • C 11 使用基于范围的for循环对作为类成员的std::向量进行迭代的代码是什么?我尝试了以下几个版本:

  • 问题内容: 我有关于通函的问题。 我有Rest Webservices,它会将对象返回到前端,问题是当我尝试返回具有多个引用的对象时,结果是我得到一个无限的响应,该响应会生成 这些对象是由Hibernate Code Generation自动生成的,我需要在后端使用循环引用,我只需要删除它,然后再使用Jackson将信息发送到前端即可。 控制器方法标头为: 我没有做任何明确的转换为Json的事情,