如何让C++容器类存入const指针,取出时返回非const指针?
我有如下简化版的类似代码:
struct Foo { int bar; Foo() : bar(0) {} }; class Container { Foo* foo; public: void put(const Foo* in_foo) { foo = in_foo; } Foo* get() { return foo; } }; int main() { Foo foo; Container c; c.put(&foo); Foo* pFoo = c.get(); pFoo->bar = 3; }
运行后出现报错:
main.cpp: In member function ‘void Container::put(const Foo*)’:
main.cpp:20:19: error: invalid conversion from ‘const Foo*’ to ‘Foo*’
[-fpermissive]
我希望在将Foo存入容器时承诺不会修改它,但取出时不强制Foo为const类型,请问最佳处理方式是什么?
解决方案
报错的核心原因是:C++不允许将const Foo*隐式转换为Foo*——这会破坏const的只读承诺,如果原指针指向的是真正的const对象,后续通过非const指针修改会导致未定义行为。针对你的需求,推荐以下几种处理方式,按安全程度排序:
调整接口,明确对象可变性(最推荐)
把put的参数改为Foo*,明确传入的是可修改的Foo对象。这种设计的含义是:容器仅持有对象指针,自身不会修改对象,但允许调用者后续通过get获取指针后修改。既满足你的需求,又保证类型安全。
修改后的代码:struct Foo { int bar; Foo() : bar(0) {} }; class Container { Foo* foo; public: void put(Foo* in_foo) { foo = in_foo; } Foo* get() { return foo; } }; int main() { Foo foo; Container c; c.put(&foo); Foo* pFoo = c.get(); pFoo->bar = 3; }使用const_cast(谨慎使用)
如果你必须让put接受const Foo*,可以用const_cast去除const属性,但这是不安全的——仅当你能100%确保传入的const Foo*实际指向的是非const对象时才能使用,否则修改真正的const对象会触发未定义行为。
修改后的put函数:void put(const Foo* in_foo) { foo = const_cast<Foo*>(in_foo); }提供双版本接口(复杂度较高)
若需要同时支持存入const和非const对象,可以为容器提供const/非const两套接口,但这会增加代码复杂度,且仍需注意const_cast的安全风险:class Container { Foo* foo; public: // 存入非const对象,允许取出后修改 void put(Foo* in_foo) { foo = in_foo; } // 存入const对象,仅允许取出const指针(若要取出非const仍需const_cast) void put(const Foo* in_foo) { foo = const_cast<Foo*>(in_foo); } Foo* get() { return foo; } const Foo* get() const { return foo; } };
内容的提问来源于stack exchange,提问作者livefree75

