为什么 map::iterator 导致编译错误。 C++
Why map::iterator causing compile error. C++
请看这个:
template<typename TK, typename TV>
class MetaAssociator
{
public:
void Set(TK key, TV const & value)
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
m_Map[key] = value;
}
TV Get(TK key) const
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
std::map<TK,TV>::const_iterator iter = m_Map.find(key);
return iter == m_Map.end() ? TV() : iter->second;
}
private:
mutable boost::mutex m_Mutex;
std::map<TK,TV> m_Map;
};
当我将 std::map<TK,TV>::const_iterator iter
更改为 std::map<TK,TV>::iterator
时,会导致以下编译错误:
error C2440: 'initializing' : cannot convert from stlpd_std::priv::_DBG_iter<_Container,_Traits> to stlpd_std::priv::_DBG_iter<_Container,_Traits>
谁能解释为什么?我没有修改 m_Map。为什么编译器会报错??
您的函数 Get
定义为 const
,这意味着对任何本地属性的访问必须是常量。 ::iterator
不是常数,但 ::const_iterator
是常数。
这是我通过快速 google 搜索找到的内容,可能有助于您理解。 https://www.studytonight.com/cpp/const-keyword.php
只需使用 const_iterator 就可以了。编译器不关心你是否真的修改了值,它只检查值是否为常量。
您的 MetaAssociator::Get
方法被标记为 const
,因此字段 m_Map
在该方法中也是 const
。现在,如果地图本身是 const
.
,std::map::find
只能 return 一个 const_iterator
这是有道理的 - 为什么要 return non-const 迭代器到 const 集合?
"why" 相当简单。
这里的const
:
TV Get(TK key) const
^^^^^
...意味着 this
是一个 Mediator const *
。这意味着你不能修改它的任何内容,这是通过类型系统强制执行的,阻止你直接分配 或 获得 non-const 引用、指针、迭代器等.,到内容1.
不好的部分是您收到的错误消息,坦率地说非常糟糕。我很清楚它是一个 MS VC++ 过去经常生成的。我在这里唯一可以给出的 "why" 是它在报告此类错误方面做得很差。据我所知,唯一的解决方法是使用不同的编译器。在这种情况下,更新到较新版本的 MS VC++ 可能是最简单的方法。 VC++ 2017 中的错误消息好。
- 尽管仍然可以通过(例如)获取指针或对 const 的引用来绕过此保护,然后再丢弃
const
-ness。编译器试图保护您免受错误,但如果您主动通过强制转换绕过它的保护,您就只能靠自己了。
请看这个:
template<typename TK, typename TV>
class MetaAssociator
{
public:
void Set(TK key, TV const & value)
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
m_Map[key] = value;
}
TV Get(TK key) const
{
boost::lock_guard<boost::mutex> lock(m_Mutex);
std::map<TK,TV>::const_iterator iter = m_Map.find(key);
return iter == m_Map.end() ? TV() : iter->second;
}
private:
mutable boost::mutex m_Mutex;
std::map<TK,TV> m_Map;
};
当我将 std::map<TK,TV>::const_iterator iter
更改为 std::map<TK,TV>::iterator
时,会导致以下编译错误:
error C2440: 'initializing' : cannot convert from stlpd_std::priv::_DBG_iter<_Container,_Traits> to stlpd_std::priv::_DBG_iter<_Container,_Traits>
谁能解释为什么?我没有修改 m_Map。为什么编译器会报错??
您的函数 Get
定义为 const
,这意味着对任何本地属性的访问必须是常量。 ::iterator
不是常数,但 ::const_iterator
是常数。
这是我通过快速 google 搜索找到的内容,可能有助于您理解。 https://www.studytonight.com/cpp/const-keyword.php
只需使用 const_iterator 就可以了。编译器不关心你是否真的修改了值,它只检查值是否为常量。
您的 MetaAssociator::Get
方法被标记为 const
,因此字段 m_Map
在该方法中也是 const
。现在,如果地图本身是 const
.
std::map::find
只能 return 一个 const_iterator
这是有道理的 - 为什么要 return non-const 迭代器到 const 集合?
"why" 相当简单。
这里的const
:
TV Get(TK key) const
^^^^^
...意味着 this
是一个 Mediator const *
。这意味着你不能修改它的任何内容,这是通过类型系统强制执行的,阻止你直接分配 或 获得 non-const 引用、指针、迭代器等.,到内容1.
不好的部分是您收到的错误消息,坦率地说非常糟糕。我很清楚它是一个 MS VC++ 过去经常生成的。我在这里唯一可以给出的 "why" 是它在报告此类错误方面做得很差。据我所知,唯一的解决方法是使用不同的编译器。在这种情况下,更新到较新版本的 MS VC++ 可能是最简单的方法。 VC++ 2017 中的错误消息好。
- 尽管仍然可以通过(例如)获取指针或对 const 的引用来绕过此保护,然后再丢弃
const
-ness。编译器试图保护您免受错误,但如果您主动通过强制转换绕过它的保护,您就只能靠自己了。