在printMessage中,如果使用索引访问常量类的向量,它可以正常工作,但不能使用迭代器(* itr)。如果迭代器声明为constant_iterator,那么它可以正常工作。
为什么呢?
在这两种情况下,我都在阅读数据,而不是修改矢量。有人可以解释一下吗?
#include <iostream>
#include <vector>
#include <sstream>
//Set this define to enable the block to compile.
#define WILL_WORK 1
#define WILL_NOT_WORK !WILL_WORK
class TestMessage
{
public:
TestMessage(){};
typedef std::vector<int> TestVec;
typedef std::vector<int>::iterator TestItr;
//The const iterator will work
//typedef std::vector<uint32_t>::const_iterator TestItr;
typedef std::vector<int>::size_type TestSize;
TestVec m_testVector;
};
void printMessage(const TestMessage & tmessage)
{
std::ostringstream asciiMessage;
asciiMessage << tmessage.m_testVector.size() << ",";
#if WILL_NOT_WORK
//This will not work
// MS Visual Studio
// error C2440: 'initializing' : cannot convert from
// 'std::_Vector_const_iterator<_Ty,_Alloc>' to
// 'std::_Vector_iterator<_Ty,_Alloc>'
// GCC
// error: conversion from
// '__gnu_cxx::__normal_iterator<const int*,
// std::vector<int, std::allocator<int> > >'
// to non-scalar type
// '__gnu_cxx::__normal_iterator<int*,
// std::vector<int, std::allocator<int> > >'
// requested
for (TestMessage::TestItr itr = tmessage.m_testVector.begin();
itr != tmessage.m_testVector.end();
++itr)
{
asciiMessage << *itr;
}
#endif
#if WILL_WORK
// This will work
for(TestMessage::TestSize index = 0;
index < tmessage.m_testVector.size();
++index)
{
asciiMessage << tmessage.m_testVector[index] << ",";
}
#endif
asciiMessage << std::endl;
std::cout << asciiMessage.str();
}
int main()
{
TestMessage message;
message.m_testVector.push_back(10);
message.m_testVector.push_back(20);
message.m_testVector.push_back(30);
message.m_testVector.push_back(40);
printMessage(message);
return 0;
}
答案 0 :(得分:4)
有2个不同的[]运算符。一个const,一个非const。
const- []运算符返回一个const-reference,因此无法更改索引处的值。
普通迭代器是非const的,这意味着编译器可能认为您可以更改向量。毕竟,您可以将迭代器传递给函数,然后编译器无法保证被调用函数不会更改迭代器/向量的内容。
因此,还有一个const_iterator。 const_iterator不能用于更改向量中的值。这可以由编译器直接检查。 如果将const_iterator传递给函数,编译器只能假定被调用函数的行为应该是这样,即不改变const_iterator指向的位置。
答案 1 :(得分:0)
不允许在常量元素的向量上使用迭代器(而不是const_iterator)。迭代器允许您修改vector元素并读取它。编译器不会检查您是否执行修改它;它只是禁止使用迭代器。 const_iterator允许您读取const元素。
答案 2 :(得分:0)
因为(非常量)迭代器 允许您修改对象,即使您不这样做也是如此。 C ++的const执行完全基于类型 - 要根据您的操作强制执行,它必须对您写入的内容进行运行时监视。如果没有严重的性能问题,需要认真的硬件支持。
答案 3 :(得分:0)
您将TestMessage
对象作为const引用传递给printMessage
。因此,当您尝试迭代此对象向量时,编译器需要const_iterator
。由于无法将其转换为非const迭代器(无法自动将int*
转换为const int*
(这些迭代器的底层实现),因此编译将失败。
但是,当你对向量使用operator[]
时,你会自动获得所需位置的int
的const引用,考虑到这个运算符有一个重载版本来处理常量。
如果您将printMessage
的声明更改为此void printMessage(TestMessage & tmessage)
,则会进行编译。但是你应该不这样做,因为你会破坏const-correcteness,因为你的打印消息函数显然无意修改作为参数传递的TestMessage
对象。