4

我对 C++11 很陌生,迭代器和统一初始化存在问题,我不明白。

考虑以下示例,该示例无法编译:

#include <iostream>
#include <vector>

int main() {

    std::vector<int> t{1, 2, 3, 4, 5};
    auto iter{t.begin()};                   

    for (; iter != t.end(); ++iter) {
        std::cout << *iter;
    }

    return 0;
}

在第 6 行中,使用统一初始化来初始化向量。在第 7 行中,我尝试对迭代器做同样的事情。这没用。将第 7 行更改为auto iter = t.begin()可以。我知道我可以为此简单地使用“基于范围”,但问题是:为什么统一初始化不适用于迭代器,但适用于基本类型,例如int i{0};

4

2 回答 2

4

当您使用初始化器列表作为初始化器时auto,声明的变量被推导出为初始化器列表。换句话说,iter被声明为std::initializer_list<vector<int>::iterator>,而不是vector<int>::iterator你所期望的。

将其更改为auto iter = t.begin()是最好的方法。

于 2014-06-15T20:28:07.630 回答
3

C++11 有一个特殊的规则auto和括号初始化,它被推断为std::initializer_list. 在您的情况下,您的选择是以下之一:

auto iter(t.begin());
auto iter = t.begin();

该行为描述于:

§7.1.6.4/7auto说明符 [dcl.spec.auto]

令 T 为变量的声明类型或函数的返回类型。如果占位符是自动类型说明符,则使用模板参数推导规则确定推导类型。如果推导是针对 return 语句并且初始化程序是一个花括号初始化列表 (8.5.4),则程序是非良构的。否则,通过将出现的 auto 替换为新发明的类型模板参数 U 或如果初始化器是花括号初始化列表,则使用 std::initializer_list从 T 中获取 P. 使用从函数调用 (14.8.2.1) 中的模板参数推导规则推导出 U 的值,其中 P 是函数模板参数类型,初始值设定项是相应的参数。如果扣除失败,则声明格式错误。否则,通过将推导的 U 代入 P 来获得为变量或返回类型推导的类型。

(强调我的)。

Scott Meyer 最近发表了一篇关于这个问题的演讲。我建议看视频。

于 2014-06-15T20:27:58.563 回答