简体   繁体   English

C++ 中的常量正确性

[英]Const correctness in C++

I have simple data structure called array (similar to std::array).我有一个简单的数据结构叫做array (类似于 std::array)。 array class have method called all() . array类有名为all()方法。 Here are method declarations:以下是方法声明:

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

range is class template, which is constructed by two iterators. range是类模板,由两个迭代器构造而成。 Here is simplified version of range class declaration:这是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;
};

So basically, if I call method all on const array object, it should call const overload of method and return const range .所以基本上,如果我在const array对象上调用所有方法,它应该调用方法的const重载并返回const range Now, in my algorithms section, I have simple algorithm with following signature:现在,在我的算法部分,我有带有以下签名的简单算法:

    template <typename UnaryFunction>
    range forEach(UnaryFunction function);

Then I tried following test:然后我尝试了以下测试:

void test1(const array<int, 10>& array)
{
    auto r = array.all();
    r.forEach([](int i) { std::cout << i << " "; });
}

And second one:第二个:

void test2(const array<int, 10>& array)
{
    auto r = array.all();
    r.forEach([](int& i) { ++i; });
}

In first case, where I was just printing variable i , compiler did not complained, even though I called non- const range method on const range object.在第一种情况下,我只是打印变量i ,编译器没有抱怨,即使我在const range对象上调用了非const range方法。 In second case, compiler complained.在第二种情况下,编译器抱怨。 Is this behaviour standard confornant?这种行为是否符合标准?

As a compiler, I am using MSVS compiler.作为编译器,我使用的是 MSVS 编译器。

auto works just like template argument deduction, which means that it drops top-level references and top-level const & volatile qualifiers. auto就像模板参数推导一样工作,这意味着它删除顶级引用和顶级constvolatile限定符。 In other words, your r is of type range<const_pointer_type> in both cases.换句话说,在这两种情况下,您的r都是range<const_pointer_type>类型。

Returning a const -qualified object should only be done in very special circumstances when you understand all details of its behaviour and really know that you want them.只有在非常特殊的情况下,当您了解其行为的所有细节并真正知道您想要它们时,才应该返回一个const限定的对象。

Normally, you should just return objects without cv-qualifiers.通常,您应该只返回没有 cv 限定符的对象。 It will play nicer with move semantics, and will not lead to incorrect expectations.它会更好地使用移动语义,并且不会导致不正确的期望。

First.第一的。 Sice you are returning by value, it doesn't really make any difference if you are returning const range or range .由于您是按值返回,因此返回const rangerange并没有什么区别。

Second.第二。 auto r = array.all(); creates a copy of whatever was returned by all .创建all返回的任何内容的副本。 Your r is a non-const object, and non-const forEach is used.您的 r 是一个非常量对象,并且使用了非常量forEach But since the iterator is const in the second version, you can't modify the iterable.但是由于迭代器在第二个版本中是 const ,因此您无法修改可迭代对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM