【问题标题】:Const method returning non-const reference compiles返回非常量引用的 const 方法编译
【发布时间】:2018-01-30 09:54:12
【问题描述】:

我有一个简单的Vector 类,实现了索引运算符。 来自this 和其他相关问题,我不确定为什么以下代码会编译:

int main()
{
    const Vector A(5);
    cout << "A :" << A << endl;
    A[0] = 5;
    cout << "A: " << A << endl;
}

Vector.h

#pragma once
#include <iostream> 
#include <functional>

namespace vector
{
    class Vector
    {
        friend std::ostream& operator<<(std::ostream&, const Vector&);

        int n;
        int *arr; 
    public:
        Vector(int = 0); 
        ~Vector();
        Vector(const Vector&);
        Vector& operator=(const Vector&);
    private:
        void copy(const Vector&);
    public:
        int& operator[](const int) const;   
    };
}

Vector.cpp

#include "Vector.h"
#include <algorithm>
#include <utility>
#include <functional>


namespace vector
{ 
    Vector::Vector(int n) : n(n), arr(new int[n])
    {
        std::fill(arr, arr + n, 0);
    }

    Vector::~Vector()
    {
        n = 0;
        delete[] arr;
    }

    void Vector::copy(const Vector& other)
    {
        arr = new int[n = other.n];
        std::copy(other.arr, other.arr + n, arr);
    }

    Vector::Vector(const Vector& other)
    {
        copy(other);
    }

    Vector& Vector::operator=(const Vector& other)
    {
        if (this != &other)  
        {
            this->~Vector();
            copy(other);
        }
        return *this;
    }

    int& Vector::operator[](const int index) const
    {
        return arr[index];
    }

    std::ostream& operator<<(std::ostream& stream, const Vector& vec)
    {
        for (int i = 0; i < vec.n; i++)
            stream << vec.arr[i] << " ";

        return stream;
    }

}

输出:

A: 0 0 0 0 0
A: 5 0 0 0 0

返回非 const 引用(后来用于更改以前的 const 对象)的 const 方法怎么可能编译?

【问题讨论】:

标签: c++ constants


【解决方案1】:

简而言之,这是你的责任。

const成员函数中,只有数据成员本身变成const。对于arr(应该是int*类型),它将变为int * const(即const指针),而不是int const *(即指向const的指针);即指针变为const,但指针没有。所以从技术上讲,可以返回一个指向指针的非常量引用,即使实际上它可能没有多大意义。

您最好在operator[] 上重载,就像大多数 STL 容器一样。例如

// const version
int const & Vector::operator[](const int index) const 
{
    return arr[index]; 
}

// non-const version
int & Vector::operator[](const int index)
{
    return arr[index]; 
}

【讨论】:

  • 您可以补充一点,为了实现 const 正确性,您通常提供 operator[] 的 const 和非常量重载以及 const 和非常量返回类型。
  • 我总是这样做,这仅用于练习目的。只想看看方法的非常量版本会发生什么。
  • 没有理由为什么成员不能是可变的;此时返回非常量引用很有意义。 (例如互斥体的集合)
【解决方案2】:

方法声明中的const 仅表示该方法对实例本身具有只读访问权限(就像它接收const MyType *this 而不是MyType *this)。如果arr 是你的类中指向int 的指针,则在const 方法中使用时将分别视为int * const。但请注意,它与const int * 不一样!这就是为什么取消引用它会产生int&amp;,而不是const &amp;int

【讨论】:

    猜你喜欢
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 2020-11-07
    • 2011-06-24
    相关资源
    最近更新 更多