C++ 中的常量正确性

Const correctness in C++

我有一个名为 array 的简单数据结构(类似于 std::array)。 array class 有一个名为 all() 的方法。以下是方法声明:

const range<const_type_pointer> all() const;
range<type_point> all();

range是class模板,由两个迭代器构造。这是 range class 声明的简化版本:

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 方法重载和 return 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编译器。

auto 就像模板参数推导一样工作,这意味着它会删除顶级引用和顶级 const & volatile 限定符。换句话说,在这两种情况下,您的 r 都是 range<const_pointer_type> 类型。

只应在非常特殊情况下返回一个符合const条件的对象,当您了解其行为的所有细节并且确实 知道你想要它们。

通常,您应该 return 个没有 cv 限定符的对象。它将更好地处理移动语义,并且不会导致不正确的期望。

首先。由于您按价值返回,因此如果您返回 const rangerange.

并没有什么区别

其次。 auto r = array.all(); 创建 all 返回的任何内容的副本。你的 r 是一个非常量对象,并且使用了非常量 forEach 。但是由于迭代器在第二个版本中是const,所以你不能修改iterable。