C ++中的Const正确性

时间:2016-03-11 20:11:06

标签: c++ const-correctness

我有一个名为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对象上调用all,它应该调用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编译器。

2 个答案:

答案 0 :(得分:1)

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

当您了解其行为的所有详细信息并且确实知道您想要它们时,只应在非常特殊情况下返回const限定对象

通常,您应该只返回没有cv-qualifiers的对象。移动语义会更好,并且不会导致不正确的期望。

答案 1 :(得分:1)

首先。如果您要返回const rangerange,那么您将按价值返回,这并没有什么区别。

二。 auto r = array.all();创建all返回的任何内容的副本。您的r是非const对象,并且使用非const forEach。但由于迭代器在第二个版本中是const,因此无法修改迭代。