【问题标题】:Why is the array constant?为什么数组是常数?
【发布时间】:2021-05-26 21:57:38
【问题描述】:

这个问题是Why is alloca returning the same address twice? 的后续问题。我找到了一种使用数组为两个实例获取不同内存地址的方法。

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];
    };

ma​​in.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 &amp;'

由于返回值是'data[index]',这一定意味着它是常数,但是,我没有将它定义为常数,为什么会发生这种情况?

【问题讨论】:

    标签: c++ class constants overloading


    【解决方案1】:

    您错过了const 的返回类型operator()()

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

    当你用const修饰符声明成员函数时,里面的所有类成员在里面使用时都变成常量

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

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

    【讨论】:

    • 我不希望它是 const,因为我想在调用 a(1) = 3; 时更改 data[index]。我定义了 data[index] in_type data[index] 没有 const 前缀,那为什么是 const 呢?
    • 那么你不应该将你的函数设为常量:in_type &amp; operator()(int index) { return data[index]; }
    • 谢谢它现在有效!!!我认为最后的 const 使得函数本身不能改变任何东西所以我认为既然它返回一个值,它应该被标记为 const
    • @JoshuaPasa 函数末尾的const 表示该函数可以安全地调用对象的const 实例。
    【解决方案2】:

    对于初学者来说,这个构造函数

    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 );
    

    【讨论】:

      【解决方案3】:

      为了修复它,你必须重载 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,所以方法不能返回引用但它必须返回一个 const 引用,即使使用非 const 方法,你也可以使用此方法,但是您无法更改成员的值,这就是您需要in_type operator()(int index) 的原因。 重要的是,当您将方法限定为 const 时,这意味着它也可用于 const 对象,因此它必须像处理 const 一样处理任何成员。

      【讨论】:

        猜你喜欢
        • 2010-10-05
        • 2012-11-08
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        • 2011-03-15
        • 2022-08-04
        • 2018-01-24
        • 2020-06-22
        相关资源
        最近更新 更多