我的google-fu不允许我找到任何关于此的内容,所以我在这里问。
我通过cppcheck运行我的c ++代码,并且它报告了assert
调用中的某些代码可能有潜在的副作用。我以较小的规模复制了这个问题:
struct Obj
{
int* myInt;
Obj() : myInt( new int(3) ) {}
~Obj() { delete myInt; }
const int* getInt() const { return myInt; }
};
struct C
{
Obj* myObj;
C() : myObj( new Obj() ) {}
~C() { delete myObj; }
const Obj* getObj() const { std::cout << "const" ; return myObj; }
Obj* getObj() { std::cout << "non const" ; return myObj; }
};
int main()
{
C c;
assert( c.getObj()->getInt() ); // Outputs "non const"
return 0;
}
(Qazxswpoi)
cppcheck是对的,这里:使用的Code on Coliru方法不是getObj()
方法,它是非常数方法。
目标是1)满足cppcheck和2)确保这些断言没有副作用。
我怎么能告诉编译器使用const
版本而不是非const getter?
我虽然有一种方法可以达到这个目的,但我发现它非常不干净,我宁愿在这种情况下使用更传统的方法来做这件事:const
是基础对象。
const_cast
由于c不是const:
assert( const_cast<const C&>(c).getObj()->getInt() );
执行非const版本。在C ++ 17中,您可以使用C c;
c.getObj();
:
std::as_const()
这比你的建议略好:
assert( std::as_const(c).getObj()->getInt() );
如果c ++ 17不可用,您可以实现自己的as_const,并在断言语句中使用它:
assert( const_cast<const C&>(c).getObj()->getInt() );
并使用它:
template <class T>
const T & as_const(T& obj)
{
return obj;
}
template <class T>
void as_const(const T&& obj) = delete;
必须添加::前缀以避免因std命名空间中的对象的ADL导致std :: as_const的歧义。