- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
如果 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 bothstd::initializer_list
method could returniterator
, when they always returnconst_iterator
.
其实这个比喻不太恰当。 std::vector
的功能begin()
,例如,返回 iterator
在非 const
上调用时std::vector
的实例(即可变元素,其元素可以修改、添加和删除),以及 const_iterator
在 const
上调用时实例(即不可变的实例,其内容无法更改):
#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 typeconst E
. [...]
因为初始化列表是 const
的集合元素,cbegin()
和 cend()
函数实际上会做与 begin()
完全相同的事情。和 end()
做。
事实上,iterator
和 const_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/
以下代码使静态断言失败: #include #include #include int main() { int theArr[] = { 1, 2, 3, 4, 5, 6, 7, 8,
我已经在映射的键上定义了两个迭代器: template struct MapKeyIterator : MyMap::iterator { using Base = typename MyMa
我想知道为什么在 C++11 中引入了 cbegin 和 cend ? 在哪些情况下调用这些方法与 begin 和 end 的 const 重载有区别? 最佳答案 这很简单。假设我有一个 vector
正如标题所说,我知道cbegin() 到一个unordered_map 具有常数复杂度,但是是常数复杂度的迭代器的迭代。例如:cbegin()++; c开始()+ 10; c开始()+我; cend(
我有一个类,我们称它为 ConstVector,它只定义 cbegin/cend 而不是 begin/end,因为我不想在构造后对其成员进行修改。我尝试像这样使用基于范围的 for 循环: Const
所以我可以这样做: for(const auto i : { 13, 42 }) cout (cout, " ")); 它给我错误: error: no matching function for c
这个问题指的是: When should I use the new ranged-for and can I combine it with the new cbegin/cend? 基于那个问题,
C++11引入了没有constexpr-说明符的std::begin()非成员函数,然后C++14更新为constexpr- std::begin() 用于数组类型 (T (&)[N]) 并附加 co
Qt 5.0 在不同的容器类中引入了迭代器方法cbegin() 和cend(),例如QList。或 QMap . 但是这些类中也有 constBegin() 和 constEnd() 方法。 所有这些
这个问题已经有答案了: What is the difference between cbegin and begin for vector? (2 个回答) 已关闭 5 年前。 虽然当我们遍历beg
我正在尝试计算 vector 中长度大于 6 的字符串的数量。这非常简单,但我正在尝试使用 algorithm 库中的 count_if 来完成。所以这是我的代码: int string_size_c
Scott Mayers 的“Effective Modern C++”中的第 13 条指出,const_iterators 优于迭代器。我同意,但我也想使用非成员函数而不是成员函数。根据这本书,在
如果我取消注释该行,有人可以解释为什么以下内容无法编译吗foo::const_iterator j = f.begin();,但是如果我使用行 foo::const_iterator j = f.cb
哪个版本的 gcc 编译器支持容器的免费 const_iterator 方法,例如:cbegin、cend、crbegin,crend。我使用带有 -std=c++0x 标志启用的 c++0x 功能的
当然,C++11 中新的 ranged-for 将非常简洁和有用。据我了解它是如何工作的,它通过尝试 *Argument-Depending-Lookup"( ADT)。 但另一个补充是,所有容器 现
如果 std::initializer_list 中的元素总是 const 值,为什么我们有像 begin()/end() 这样的模板方法而不是 cbegin()/cend()?这个名称(按照惯例,与
成员(member)begin有两个重载,其中之一是 const_iterator begin() const;。还有cbegin const_iterator cbegin() const noex
我不得不编写 C++11 代码,但我想使用 std::cbegin()。所以,我正在查看 GCC 5.4.0 的实现,在我的系统上的 /usr/include/c++/5/bits/range_acc
所以,为了让代码如 auto vect = ...; auto it = vect.begin(), end = vect.end(); // want const_iterator, getting
cppreference为 std::cbegin 显示此签名: template constexpr auto cbegin( const C& c ) -> decltype(std::begin
我是一名优秀的程序员,十分优秀!