gpt4 book ai didi

c++ - 没有 cbegin()/cend() 的 std::initializer_list

转载 作者:IT老高 更新时间:2023-10-28 21:47:06 27 4
gpt4 key购买 nike

如果 std::initializer_list 中的元素总是 const 值,为什么我们有像 begin()/end() 这样的模板方法而不是 cbegin()/cend()?这个名称(按照惯例,与例如 std::vector 相比)可能表明两个 std::initializer_list 方法都可以返回 iterator,当它们总是返回 const_iterator

最佳答案

虽然我无法深入了解 cbegin() 的原因和 cend()不属于std::initializer_list的界面除了 begin()end() ,当然有充分的理由说明为什么最后两个成员函数应该在那里。

一个原因是,例如,基于范围的 for循环由 C++11 标准精确定义为函数 begin()end() (第 6.5.4/1 段)。因此,为了使它可以与初始化列表一起使用,std::initializer_list必须提供begin()end()成员函数:

#include <utility>
#include <iostream>

int main()
{
auto l = { 1, 2, 3, 4, 5 };
for (int x : l) // Works because std::initializer_list provides
// the member functions begin() and end().
{
std::cout << x << " ";
}
}

此外,考虑成员函数 cbegin() 是有意义的。和 cend()在 C++11 之前不存在:因此,有 begin()end()std::initializer_list的界面上允许根据 begin() 编写旧的通用算法和 end()也可以使用初始化列表,而无需重写它们。

你写:

These names (by conventions, comparing to e.g. std::vector) could suggest that both std::initializer_list method could return iterator, when they always return const_iterator.

其实这个比喻不太恰当。 std::vector的功能begin() ,例如,返回 iterator在非 const 上调用时std::vector 的实例(即可变元素,其元素可以修改、添加和删除),以及 const_iteratorconst 上调用时实例(即不可变的实例,其内容无法更改):

#include <vector>
#include <type_traits>

int main()
{
// A non-const vector...
std::vector<int> v = { 1, 2, 3, 4, 5 };

auto i = v.begin();
static_assert(
std::is_same<decltype(i), decltype(v)::iterator>::value,
// ^^^^^^^^
// ...non-const iterator!
"What?");

// A const vector...
std::vector<int> const vc = { 1, 2, 3, 4, 5 };
auto ic = vc.begin();
static_assert(
std::is_same<decltype(ic), decltype(vc)::const_iterator>::value,
// ^^^^^^^^^^^^^^
// ...const iterator!
"What?");
}

根据定义,初始化列表是不可变的集合。根据 C++11 标准的第 18.9/2 段:

An object of type initializer_list<E> provides access to an array of objects of type const E. [...]

因为初始化列表是 const 的集合元素,cbegin()cend()函数实际上会做与 begin() 完全相同的事情。和 end()做。

事实上,iteratorconst_iterator都定义为指向初始化器列表值类型的常量元素的指针,因此是否是 begin() 的情况值得商榷。和 end()总是返回 const_iterator (如您所想),或者他们是否总是返回 iterator .

这就是 C++11 标准的第 18.9/1 段如何定义 initializer_list类模板:

namespace std {
template<class E> class initializer_list {
public:
typedef E value_type;
// ...
typedef const E* iterator;
typedef const E* const_iterator;
// ...
constexpr const E* begin() const noexcept; // first element
constexpr const E* end() const noexcept; // one past the last element
};

// ...
}

关于c++ - 没有 cbegin()/cend() 的 std::initializer_list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15623472/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com