当然,C++ 11中新的ranged-for将非常简洁和有用.据我了解它是如何工作的,它会查找"容器" begin并end尝试*Argument-dependent-Lookup"(ADT).
但另一个补充是,所有容器现在都拥有cbegin()并cend()获得const_iterators容器.
我有点困惑,一方面是我想我应该用cbegin()我如果不是,要修改的容器,另一方面我必须添加额外的const内部范围,为获得同样的事情.
所以,它看起来像这样:
// print all
for(const auto elem : data)
cout << elem
Run Code Online (Sandbox Code Playgroud)
使用ADT,找到data.begin(),因此const需要.
VS
// print everything but the first (a reason not to use range-for)
for(auto it = data.cbegin()+1; it!=data.cend(); ++it)
cout << *it
Run Code Online (Sandbox Code Playgroud)
使用data.cbegin(),因此const不需要.
但这不是更"惯用"吗?:
// print everything but the first (a reason not to use range-for) …Run Code Online (Sandbox Code Playgroud) 我有一个类,我们称之为ConstVector,它只定义cbegin/cend而不是begin/end,因为我不想在构造之后允许对其成员进行修改.我尝试使用基于for循环的范围,如下所示:
ConstVector const_vector(1, 2, 3);
for(const auto &x : const_vector)
....
Run Code Online (Sandbox Code Playgroud)
虽然该课程的相关部分如下所示:
template<class T>
class ConstVector
{
public:
ConstVector(std::initializer_list<T> values);
typename std::vector<T>::const_iterator cbegin(void) const;
typename std::vector<T>::const_iterator cend(void) const;
private:
std::vector<T> data;
};
template<class T>
ConstVector::ConstVector(std::initializer_list<T> values)
: data(values)
{
}
template<class T>
typename std::vector<T>::const_iterator ConstVector<T>::cbegin() const
{
return this->data.cbegin();
}
template<class T>
typename std::vector<T>::const_iterator ConstVector<T>::cend() const
{
return this->data.cend();
}
Run Code Online (Sandbox Code Playgroud)
但我的编译器抱怨:
‘begin’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
我的问题是:我必须实现开始/结束吗?据我所知,它应该选择cbegin/cend,如果它const auto &x不是auto &x.至少这对我来说是有意义的.如果我删除基于for循环的范围,一切都编译得很好.
我也尝试过这里提出的所有内容const …
我第一次尝试编写一个基于for循环的范围来迭代unique_ptrs我写道:
std::vector<std::unique_ptr<Foo>> vec;
// Initialize vec
for (auto v : vec) // error
{}
Run Code Online (Sandbox Code Playgroud)
然后我意识到这是尝试使用unique_ptr创建每个元素的副本.那么我把它写成参考:
for (auto& v : vec)
{}
Run Code Online (Sandbox Code Playgroud)
在它前面添加一个const使我无法更改指针.
for (const auto& v : vec)
{
v = nullptr; // error (good!)
}
Run Code Online (Sandbox Code Playgroud)
如何编写它,以便指向的数据无法更改?例如,以下代码不应编译.
for (??? v : vec)
{
v->func();
}
class Foo
{
public:
void func();
private:
bool mBar;
}
Foo::func()
{
mbar = true; // Should cause error
}
Run Code Online (Sandbox Code Playgroud) 随着C++ 11的出现,我们有unordered_map.cbegin/cend来专门返回const_iterator的值.所以在表达式"auto it = unordered_map.cbegin()"中推导出的'it'类型是const_iterator.
但是,当谈到unordered_map.find(key)函数时,我认为可能缺少一个"cfind()"对应物,它特意返回一个const_iterator.
有人说我们可以使用"const auto it = unordered_map.find(key)"来获取"const迭代器",但我强烈怀疑"const iterator"是相同的"const_iterator",其中"const iterator"的限制改变迭代器本身的能力,而"const_iterator"限制了改变迭代器引用的内容的能力.
所以,真的,如果我们想充分利用"自动"类型演绎(了解混淆或"自动"类型演绎的变化 - auto,auto&,const auto等),我怎么能有unordered_map .find(key)返回一个"const_iterator"而不必我明确指定"const_iterator" - 这就是auto的所有最佳用例之后!
下面是一个演示编译器行为的简单示例代码:
#include "stdafx.h"
#include <unordered_map>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::unordered_map<int, int> umiit;
umiit umii;
auto it0 = umii.find(0);
it0->second = 42;
const auto it1 = umii.find(0);
it1->second = 42;
umiit::const_iterator it2 = umii.find(0);
it2->second = 42; // expected compiler error: assigning to const
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我理解这个问题的内容,但是当使用函数重载时,它是如何工作的?
例如,std::map定义了以下方法:
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
Run Code Online (Sandbox Code Playgroud)
如何使用auto关键字选择一个或另一个?像下面这样的东西对我来说似乎不正确:
auto i = mymap.find(key); //calls the non-const method?
const auto i = mymap.find(key); //calls the const method?
Run Code Online (Sandbox Code Playgroud) c++ ×4
c++11 ×3
auto ×1
const ×1
for-loop ×1
foreach ×1
idioms ×1
overloading ×1
unique-ptr ×1