我想改变a中的元素set,所以我使用了set<T>::iterator.但是,编译器认为"元素是const".然后我意识到那set<T>::iterator是const_iterator......
那么,我怎么能改变这个元素呢?删除它然后插入一个新的?
随着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) // Cat.h
class Cat
{public:
void const_meow() const{ ... };
void meow(){ ... };
};
class CatLibrary
{public:
std::vector<std::shared_ptr<Cat>>::iterator begin()
{
return m_cat_list.begin();
}
// compile error, the compiler complains cannot covert type
// from `std::vector<std::shared_ptr<Cat>>::const_iterator`
// to `std::vector<std::shared_ptr<const Cat>>::const_iterator`
std::vector<std::shared_ptr<const Cat>>::const_iterator begin() const
{
return m_cat_list.cbegin();
}
private:
std::vector<std::shared_ptr<Cat>> m_cat_list;
};
Run Code Online (Sandbox Code Playgroud)
// main.cpp
CatLibrary cat_library;
cat_library.add(std::make_shared<Cat>());
cat_library.add(std::make_shared<Cat>());
for(auto& cat: cat_library )
{
cat->const_meow();
cat->meow();
}
for(const auto& cat: cat_library)
{
cat->const_meow();
cat->meow(); // hope to compile error due to …Run Code Online (Sandbox Code Playgroud) 我试图理解const_iterator的含义.我有以下示例代码:
void CustomerService::RefreshCustomers()
{
for(std::vector<Customer*>::const_iterator it = customers_.begin();
it != customers_.end() ; it ++)
{
(*it)->Refresh();
}
}
Run Code Online (Sandbox Code Playgroud)
Refresh()是Customer类中的方法,它没有定义为const.起初以为我认为const_iterator应该禁止修改容器的元素.但是,此代码无需投诉即可编译.这是因为有一个额外的间接水平吗?const_iterator到底是什么意思?
UPDATE
在这种情况下,使用const_iterator是最佳做法吗?
我正在C++中自己实现Vector.这是一个两部分问题.
第1部分:尝试迭代Vector时,我的begin()和end()迭代器无法处理输入参数.下面是我的整个Vector.h实现:
class iterator{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
Vector<T>* ptr;
uint64_t position;
COMLINK slave;
void init(void){
ptr = nullptr;
position = 0;
}
void copy(const iterator& i){
init();
ptr = i.ptr;
position = i.position;
slave = i.slave;
}
void move(iterator&& i){
init();
std::swap(ptr, i.ptr);
std::swap(position, i.position);
std::swap(slave, i.slave);
}
iterator(void){
init();
}
iterator(const iterator& q){
copy(q);
}
explicit iterator(Vector<T>* v, uint64_t offset){
init();
ptr = v;
position = offset;
slave = v->master;
}
T& operator*(void){
if ((position …Run Code Online (Sandbox Code Playgroud) #include <string>
#include <iostream>
int main() {
std::string s = "abcdef";
std::string s2 = s;
auto begin = const_cast<std::string const &>(s2).begin();
auto end = s2.end();
std::cout << end - begin << '\n';
}
Run Code Online (Sandbox Code Playgroud)
此代码将结果begin() const与结果混合end().这些函数都不允许使任何迭代器无效.但是我很好奇是否要求end()使iterator变量无效begin实际意味着该变量begin是可用的end.
考虑一个C++ 98,写时复制的实现std::string; 非const begin()和end()函数会导致复制内部缓冲区,因为这些函数的结果可用于修改字符串.所以begin上面开始时都有效s和s2,而是使用非const的end()构件使之不再有效s2,产生它的容器.
上面的代码通过copy-on-write实现产生"意外"结果,例如libstdc ++.libstdc ++ 不是end - begin相同s2.size(),而是产生另一个数字.
是否导致begin …
这段代码是我试图在其他地方做的事情的简化测试.我有一个函数,它接受一个"ref-to-ptr"参数并修改它以从指针列表返回一个指针.
#include <iostream>
#include <list>
using namespace std;
typedef int* intp;
typedef std::list<intp> intplist;
intplist myList;
void func(intp &arg) // (1)
{
intplist::const_iterator it = myList.begin();
std::advance(it, 2);
arg = *it;
}
int main()
{
myList.push_back(new int(1));
myList.push_back(new int(2));
myList.push_back(new int(3));
int* ip = NULL; // (2)
func(ip);
if (ip) cout << "ip = " << *ip << endl;
else cout << "ip is null!" << endl;
for (intplist::const_iterator it = myList.begin(); it != myList.end(); ++it)
delete *it;
return 0; …Run Code Online (Sandbox Code Playgroud) c++ pointers pass-by-reference undefined-behavior const-iterator
我正在尝试编写一个类,它应该作为一些基础元素序列的排序视图.到目前为止,我已经提出了非const版本.现在我在调整它以提供const_iterator功能方面遇到了问题.
到目前为止我的代码看起来像这样:
// forward declare iterator
template <class InputIt>
class sorted_range_iter;
template <class InputIt>
class sorted_range {
friend class sorted_range_iter<InputIt>;
private:
using T = typename InputIt::value_type;
InputIt _first;
InputIt _last;
std::vector<size_t> _indices;
public:
using iterator = sorted_range_iter<InputIt>;
sorted_range() = default;
sorted_range(InputIt first, InputIt last)
: _first(first), _last(last), _indices(std::distance(_first, _last)) {
std::iota(_indices.begin(), _indices.end(), 0);
};
template <class Compare = std::less<T>>
void sort(Compare comp = Compare()) {
std::sort(_indices.begin(), _indices.end(),
[this, &comp](size_t i1, size_t i2) {
return comp(*(_first + …Run Code Online (Sandbox Code Playgroud) 出于某种原因,以下代码给出了错误Symbol 'TemplateBase' could not be resolved.:
template <typename T>
class TemplateBase
{
TemplateBase(std::map<std::string, T>::const_iterator anIterator)
{ }
};
class SubClass : public TemplateBase<int>
{
SubClass(std::map<std::string, int>::const_iterator anIterator) :
TemplateBase<int>(anIterator) //Error: Symbol 'TemplateBase' could not be resolved.
{ }
};
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当我删除::const_iterator并且仅std::map<std::string, int>剩下时,没有出现错误:
template <typename T>
class TemplateBase
{
TemplateBase(std::map<std::string, T> aMap)
{ }
};
class SubClass : public TemplateBase<int>
{
SubClass(std::map<std::string, int> aMap) :
TemplateBase<int>(aMap) //No error.
{ }
};
Run Code Online (Sandbox Code Playgroud)
另外,以下函数也没有给出错误,因此它似乎与模板基类调用与const_iterator的组合有关:
void function()
{
std::map<std::string, …Run Code Online (Sandbox Code Playgroud) 这是今天的第二个编译错误让我感到困惑.不知何故,对于下面的代码,gcc抱怨代码具有返回迭代器return_iter返回冲突类型的函数std::_Rb_tree_iterator<const int*>然后std::_Rb_tree_const_iterator<const int*>,但是它们都不应该是const迭代器,因为set不是const.任何人都可以解释为什么在std::end()非const lvalue上调用该方法会返回一个const_iterator?
完整的代码粘贴在下面.
注意我只在编译时遇到此错误gcc.当我用clang编译它时,这个错误没有出现(Apple LLVM version 8.0.0 (clang-800.0.38).我正在使用的gcc版本是g++ (GCC) 5.1.0
一个相关的问题.这是正确使用前进吗?std::forward每当您想使用转发参考时,是否可以打电话?我在下面调用它的原因是为了防止类型在对象是rvalue时重载某些方法.
#include <vector>
#include <string>
#include <set>
#include <iostream>
using namespace std;
int global_value = 1;
class LessPtr {
public:
template <typename PointerComparableOne, typename PointerComparableTwo>
constexpr auto operator()(PointerComparableOne&& lhs,
PointerComparableTwo&& rhs) const {
return *std::forward<PointerComparableOne>(lhs) <
*std::forward<PointerComparableTwo>(rhs);
}
using is_transparent = std::less<void>::is_transparent;
};
template <typename Container, typename Key>
auto return_iter(Container&& …Run Code Online (Sandbox Code Playgroud)