如果std::initializer_list
中的元素总是常量值,为什么我们有模板方法,如begin()/end()
而不是cbegin()/cend()
?这个名称(按照惯例,与例如std::vector
相比)可能暗示当两个方法总是返回const_iterator
时,两个方法都可以返回iterator
。std :: initializer_list没有cbegin()/ cend()
回答
虽然我不能提供关于原因的见解,为什么cbegin()
和cend()
不std::initializer_list
“s接口另外的一部分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()
不存在前因此,在std::initializer_list
的接口上具有begin()
和end()
允许根据begin()
和end()
编写的旧通用算法也可以使用初始化器列表,而不需要它们被重写。
你写:
这些名字(按约定,比较例如
std::vector
)可能表明,这两个std::initializer_list
方法可以返回iterator
,当他们总是返回const_iterator
。
其实这个比喻不是很合适。 std::vector
的功能begin()
,例如,对std::vector
非const
实例调用时(即,可变的一个,它的元素可以被修改,添加和删除)返回一个iterator
,并且当上一个const
实例调用一个const_iterator
(即一个不变的一个,其内容不能被修改):
#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:
initializer_list<E>
类型的对象提供了访问const 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
};
// ...
}
- 1. cbegin()/ cend()vs constBegin()/ constEnd()
- 2. gcc支持cbegin和cend方法
- 3. 为什么我不能将cend()和cbegin()传递给count_if?
- 4. 对于基于循环的范围,cbegin/cend不够吗?
- 5. 在C++中支持`std :: cbegin()`14
- 6. std :: initializer_list替代
- 7. 迫使/ CEND()使用CBEGIN()的范围为基础的
- 8. 为什么Netbeans不认识`cbegin()`,`cend()`,`unordered_set`等C++特性?
- 9. 的std ::用的std :: initializer_list
- 10. 'CBEGIN' 在此范围
- 11. std :: initializer_list <int const>不能从std :: initializer_list构建<int>
- 12. 使函数指针std :: min与std :: initializer_list
- 13. 使用多维std :: initializer_list
- 14. constexpr阵列和std :: initializer_list
- 15. 使用std :: initializer_list创建树?
- 16. 别名的std :: initializer_list在铛
- 17. 的std :: initializer_list和=操作
- 18. 为什么的std :: CBEGIN返回相同类型的std ::开始
- 19. 为什么类中的initializer_list不是“const std :: initializer_list&li”?
- 20. 内存与腐败的std :: initializer_list
- 21. std :: initializer_list和元素的求值顺序
- 22. 在C++中std :: initializer_list的好处11
- 23. 意外的非常数std :: initializer_list
- 24. std :: initializer_list <>和参考参数
- 25. 与initializer_list
- 26. 的std :: initializer_list作为的std ::数组构造
- 27. 如何从std :: initializer_list构建std :: array数据结构
- 28. 为什么std :: vector和std :: array的C++ initializer_list行为不同?
- 29. 插入一个std :: initializer_list到的std ::地图
- 30. C++ 11:是否有可能从函数返回一个std :: initializer_list?
一个很好的问题。做得好。 – 2013-03-25 20:20:15
@LightnessRacesinOrbit嘿美女,很高兴在这里见到你:-) – Des1gnWizard 2016-01-07 08:57:59
@ Des1gnWizard:这不是一个交友网站,谢谢。 – 2016-01-07 10:49:05