C++ 中的 const 正确性
Posted
技术标签:
【中文标题】C++ 中的 const 正确性【英文标题】:Const correctness in C++ 【发布时间】:2016-03-11 20:11:06 【问题描述】:我有一个名为array
的简单数据结构(类似于std::array)。 array
类具有称为 all()
的方法。以下是方法声明:
const range<const_type_pointer> all() const;
range<type_point> all();
range
是类模板,由两个迭代器构造。这是range
类声明的简化版:
template <typename Iterator>
class range
typedef typename iterator_traits<Iterator>::type_value type_value;
typedef typename iterator_traits<Iterator>::type_reference type_reference;
typedef typename iterator_traits<Iterator>::type_pointer;
range(Iterator begin, Iterator end);
// methods & algorithms
// data members
mutable Iterator _begin;
mutable Iterator _end;
;
所以基本上,如果我在const array
对象上调用所有方法,它应该调用const
方法的重载并返回const range
。现在,在我的算法部分,我有以下签名的简单算法:
template <typename UnaryFunction>
range forEach(UnaryFunction function);
然后我尝试了以下测试:
void test1(const array<int, 10>& array)
auto r = array.all();
r.forEach([](int i) std::cout << i << " "; );
第二个:
void test2(const array<int, 10>& array)
auto r = array.all();
r.forEach([](int& i) ++i; );
在第一种情况下,我只是打印变量i
,编译器没有抱怨,即使我在const range
对象上调用了非const range
方法。在第二种情况下,编译器抱怨。这种行为标准符合吗?
作为编译器,我使用的是 MSVS 编译器。
【问题讨论】:
作为旁注:不要返回const T
(非参考)。它会引发细微的错误,并且不能解决任何问题。在你的情况下返回range<const_type_pointer>
例如 r.forEach([](int i) std::cout
【参考方案1】:
首先。既然您按价值返回,那么返回 const range
或 range
并没有什么区别。
第二。 auto r = array.all();
创建 all
返回的任何内容的副本。您的 r 是一个非常量对象,并且使用了非常量 forEach
。但是由于迭代器在第二个版本中是const,所以不能修改iterable。
【讨论】:
【参考方案2】:auto
就像模板参数推导一样工作,这意味着它会删除***引用和*** const
和 volatile
限定符。换句话说,您的r
在这两种情况下都是range<const_pointer_type>
类型。
返回一个const
-qualified 对象应该只在非常特殊情况下,当你了解其行为的所有细节并且真的知道你想要它们。
通常,您应该只返回不带 cv 限定符的对象。它会更好地使用移动语义,并且不会导致错误的期望。
【讨论】:
以上是关于C++ 中的 const 正确性的主要内容,如果未能解决你的问题,请参考以下文章