假设我们有一个 myType 类型的 Object obj,我们想将它传递给函数 Foo,它会返回一些关于 obj 的有值(value)的信息。函数 Bar 是声明 obj 的地方,也是从那里调用 Foo 的地方:
void Bar ()
{
myType obj; //default constructor
string valuableInfo = Foo(obj);
//do other stuff
//...
} //end of Bar()
当然,这段代码并没有过多地说明 Foo 是否将 obj 作为引用或作为值,以及 Foo 是否以任何方式修改 obj。
当然,如果 Foo 将 obj 作为值或 const 引用,我们不会有任何问题。
string Foo (const myType & input); //this is fine
string Foo (myType input); //so is this
但我们不能保证这一点!函数签名很可能是
string Foo (myType & input); //asking for trouble!!
但是检查我们想要传递 obj 的每个函数的签名非常不方便,那么我们如何指定我们只想将我们的对象传递给 promise 不修改它的函数呢?
当然,一种方法是将 obj 声明为 const,但这种方法的问题是我们失去了灵 active 。如果我们在调用 Foo(obj) 之后想在 Bar() 中修改 obj 怎么办?
void Bar ()
{
const myType obj; //default constructor
string valuableInfo = Foo(obj); //compiler will complain if Foo's signature doesnt match
//we can't modify obj here :(
//...
} //end of Bar()
明显但不好的解决方案是这样做:
void Bar ()
{
myType obj; //default constructor
const myType immutableObj {obj}; //copy ctr call
//this is expensive and not recommended if obj is big! want to avoid
string valuableInfo = Foo(immutableObj); //will get the valuable Info risk free
// compiler will complain if Foo has inappropriate signature
//do other stuff
//...
} //end of Bar()
那么这里最好的解决方案是什么?有没有办法静态断言 Foo 对我们传入的对象是非侵入性的?我们可以暂时将 obj 设为 const(无需创建新的 const 对象)或类似的东西吗?
最佳答案
foo(std::as_const(obj));
在 C++17 之前,如果你发现自己经常需要这样做,那么自己编写一个帮助程序是微不足道的:
template<class T>
constexpr typename std::add_const<T>::type& as_const(T& t) noexcept { return t; }
// prevent accidentally creating an lvalue out of a const rvalue
template<class T> void as_const(const T&&) = delete;
当然,您所做的任何事情都无法防止有人故意抛弃 constness。墨菲、马基雅维利等
关于c++ - 如何防止在非常量对象上意外调用变异函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34097504/