为什么数组是常量?

Why is the array constant?

此问题是 的后续问题。我找到了一种使用数组为两个实例获取不同内存地址的方法。

vml.h

#pragma once
#include <iostream>


namespace vml {
    // Vectors
    template <typename in_type, const int in_length>
    class vec {
    public:
        vec(in_type* in_data) {
            std::cout << data << std::endl;
            std::copy(in_data, in_data + in_length, data);
        }
        vec() {
            data = nullptr;
        }
        in_type& operator()(int index) const {
            _ASSERT(0 <= index && index < in_length);
            return data[index];

        }

    private:
        in_type data[in_length];
    };

main.cpp

#include <memory>
#include "vml.h"

int main() {
    int list[] = { 1,2,3 };
    int list2[] = {2,4,6 };

    vml::vec<int, 3> a(list);
    vml::vec<int, 3> b(list);

    a(1) = 3;
    
    return 0;
}

但是,当我 运行 代码时,我得到一个错误

Error C2440 'return': cannot convert from 'const in_type' to 'in_type &'

因为 return 的值是 'data[index]' 这一定意味着它是常量,但是,我没有将它定义为常量,所以为什么会这样?

您在 return 类型的 operator()()

中错过了 const
in_type const & operator()(int index) const {
        _ASSERT(0 <= index && index < in_length);
        return data[index];
    }

当您使用 const 修饰符声明成员函数时,内部的所有 class 成员在内部使用时变为常量

如果你想要非常量引用作为结果,你不应该在该成员函数上使用 const 修饰符:

in_type & operator()(int index) {
    _ASSERT( 0 <= index && index < in_length);
    return data[index];
}

对于初学者这个构造函数

vec() {
    data = nullptr;
}

无效。数组是不可修改的左值。

这个成员函数

    in_type& operator()(int index) const {
        _ASSERT(0 <= index && index < in_length);
        return data[index];

    }

是常量成员函数。所以数组数据被认为是一个常量数组。

你可以像这样重载函数

    const in_type& operator()(int index) const {
        _ASSERT(0 <= index && index < in_length);
        return data[index];
    } 

    in_type& operator()(int index) {
        _ASSERT(0 <= index && index < in_length);
        return data[index];
    }

在这种情况下在这个声明中

a(1) = 3;

会调用非常量成员函数

注意这个构造函数

    vec(in_type* in_data) {
        std::cout << data << std::endl;
        std::copy(in_data, in_data + in_length, data);
    }

不安全。至少参数应该有限定符 const.

构造函数可以这样声明

    vec( const in_type *in_data, size_t n );

为了修复它,您必须重载 operator() 两次

in_type const &operator()(int index) const {
    _ASSERT(0 <= index && index < in_length);
    return data[index];
}
in_type &operator()(int index) {
    _ASSERT(0 <= index && index < in_lenght);
    return data[index];
}

你必须这样做,因为当你创建一个 const 对象时,对象的任何成员都是 const,所以方法不能 return 引用但它必须 return 一个 const 引用,你即使使用非 const 方法也可以使用此方法,但您不能更改成员的值,这就是您需要 in_type operator()(int index) 的原因。 重要的是,当您将方法限定为 const 时,这意味着它也可用于 const 对象,因此它必须像处理 const 一样处理任何成员。