如果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