C++ 如何将指针映射公开为常量指针映射?
我有一个类,它的成员是指针的std::map。现在,我想以只读方式公开该成员:地图和指向的对象都不允许修改。在内部,我需要这些指针是非常量的,我想将它们公开为常量 我确实有一个至少可以编译的解决方案,但我想知道我是否会遇到任何隐藏的问题C++ 如何将指针映射公开为常量指针映射?,c++,pointers,stl,map,constants,C++,Pointers,Stl,Map,Constants,我有一个类,它的成员是指针的std::map。现在,我想以只读方式公开该成员:地图和指向的对象都不允许修改。在内部,我需要这些指针是非常量的,我想将它们公开为常量 我确实有一个至少可以编译的解决方案,但我想知道我是否会遇到任何隐藏的问题 class A { public: const std::map<int, const float*>& GetMap() const { return *(reinterpret_cast< const std::map<i
class A
{
public:
const std::map<int, const float*>& GetMap() const { return *(reinterpret_cast< const std::map<int, const float*>* >( &m_Map)); }
private:
std::map<int, float*> m_Map;
};
A类
{
公众:
const std::map&GetMap()const{return*(重新解释强制转换(&m_-map));}
私人:
std::map mu map;
};
我可以想到一个可能的问题:如果std::map的内部布局对于指针映射和常量指针映射是不同的,那么这将导致丑陋的bug。但我想不出任何合理的理由来解释这种情况。有人知道吗
澄清一下:我知道这是一种黑客行为,有更安全的解决方案(比如单独的访问函数)。我只是想知道这是否会因为我丢失的某些信息而立即中断。这当然是未定义(编辑:看起来它实际上只是未指定)的行为,因为这两个映射(从语言的角度来看)是完全不相关的类型。它现在看起来可能有用,但有时它会坏掉,引起一大堆头痛
您认为,不是公开实现细节(您在内部使用映射),而是可以为类公共接口提供<代码> COSTATIORATER < /CAR> S和A<代码>查找< /代码>方法?
编辑: 见5.2.10/7: 可以创建指向对象的指针 显式转换为指向的指针 不同类型的对象。65)除 转换类型为的右值 “指向T1的指针”指向类型“指针” 到T2”(其中T1和T2是对象 类型和路线的位置 T2的要求并不更严格 比T1)的更高)并返回到其 原始类型产生原始类型 指针值,这种 未指定指针转换 从这段引文中,我们得出结论,从具有非常量值类型的映射到具有常量值类型的映射的强制转换具有未指定的行为。此外,实际上取消对转换指针的引用可能会违反严格的别名规则,并导致未定义的行为。您可以在需要时将其作为映射保存并在内部强制转换。这是丑陋但合法的(只要你知道所有指向的值都不是常量)至少它不涉及未定义的行为,我很确定你的解决方案确实如此。尽管正如您所说,它可能在大多数平台上大部分时间都能正常工作。reinterpret\u cast会生成一个具有未指定行为的引用。不要那样做!使用常量迭代器
class A {
public:
typedef std::map<int, float*> MapType;
typedef MapType::const_iterator const_iterator;
const_iterator begin () const { return m_Map.begin(); }
const_iterator end () const { return m_Map.end(); }
private:
std::map<int, float*> m_Map;
};
void some_function () {
A my_map;
// Code to build the map elided
for (A::const_iterator iter = my_map.begin(); iter < my_map.end(); ++iter) {
do_something_with_but_not_to (*iter);
}
A类{
公众:
typedef std::map MapType;
typedef MapType::const_迭代器const_迭代器;
常量迭代器begin()常量{返回m_Map.begin();}
const_迭代器end()const{return m_Map.end();}
私人:
std::map mu map;
};
空一些函数(){
我的地图;
//删除用于构建地图的代码
对于(A::const_iterator iter=my_map.begin();iter
请注意,您还可以导出一些东西,例如返回常量迭代器的find。这可能会导致问题的一个很好的原因是:即使二进制实现通常是相同的(通常是相同的,但谁知道呢),那么类型仍然是不同的。一些容器可能会使用一些静态(或现在在C++11中的TLS)字段(例如,为了优化/调试的目的),对于不同的类型,它们必须是不同的
想象一下,这样一个字段将是一个(初始化为null的)指针,它在构造函数中被赋予了一些重要的值(如果还没有赋值的话)。只要没有构造这种类型的对象,就可以安全地假设没有人会遵从它,并且在第一次构造函数调用之后,可以在不检查它是否为非空的情况下遵从它。您的代码可以生成从未构造过的容器,但它的方法遵从内部指针,导致难以跟踪segfault。不幸的是,你可以使用一个指针类对象的映射(Ack.Actuple Posits),自动下注到