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&lt;const_type_pointer&gt; 例如 r.forEach([](int i) std::cout 【参考方案1】:

首先。既然您按价值返回,那么返回 const rangerange 并没有什么区别。

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

【讨论】:

【参考方案2】:

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

返回一个const-qualified 对象应该只在非常特殊情况下,当你了解其行为的所有细节并且真的知道你想要它们。

通常,您应该只返回不带 cv 限定符的对象。它会更好地使用移动语义,并且不会导致错误的期望。

【讨论】:

以上是关于C++ 中的 const 正确性的主要内容,如果未能解决你的问题,请参考以下文章

C++ const 正确性漏洞或意外使用?

C++ NULL 指针和 const 正确性

const 正确性如何帮助编写更好的程序?

int main(int, char const* const*) 格式正确吗?

确保正确维护 C++ 中的 Clone()

如何在 C# 中实现 const 正确性? [复制]