使用下标和等于运算符重载进行赋值和检索 [英] Assignment and retrieval using subscript and equals operator overloads

查看:69
本文介绍了使用下标和等于运算符重载进行赋值和检索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了很长时间试图解决这个问题。我想要做的是使用运算符重载,以便我的对象行为更像一个多维数组。我已经找到了几个小问题的解决方案,但每当我试图将所有问题放在一起时,都会出现这样或那样的问题,要么是左值赋值错误,要么是来自右值的无效初始化,或者只是直接的seg错误。如果您能给我提建议,我将不胜感激。

#include <iostream>
#include <vector>
#include <string> 

class Matrix {
  std::string **m;
 public:
  Matrix(int x, int y) {
    m = new std::string*[x];
    for (int i = 0; i < x; i++)
      m[x] = new std::string[y];
  }
  class Proxy {
    std::string *mm;
    int lastIndex = 0;
  public:
    Proxy(std::string *s) : mm(s) {}
      std::string &operator[](int index) {
      lastIndex = index;
      return mm[index];
    }
    std::string &operator=(std::string s) {
      mm[lastIndex] = s;
      return mm[lastIndex];
    }
  };
  Proxy operator[](int index) {
    return Proxy(m[index]);
  }
};

int main()
{
  Matrix *m = new Matrix(5, 5);
  m[2][2] = std::string("It Works");
  std::cout << m[2][2] << std::endl;
  return 0;

推荐答案

main()中,m是指向Matrix对象的指针,因此您需要取消引用该指针才能访问Matrix对象,以便可以对其调用Matrix::operator[],例如:

int main()
{
  Matrix *m = new Matrix(5, 5);
  (*m)[2][2] = "It Works";
  std::cout << (*m)[2][2] << std::endl;
  delete m;
  return 0;
}

Online Demo

否则,您的示例一开始并不真正需要指针,例如:

int main()
{
  Matrix m(5, 5);
  m[2][2] = "It Works";
  std::cout << m[2][2] << std::endl;
  return 0;
}

Online Demo

无论哪种方式,您的Proxy根本不需要实现operator=,例如:

class Proxy {
  std::string *mm;
public:
  Proxy(std::string *s) : mm(s) {}

  std::string& operator[](int index) {
    return mm[index];
  }
};
m[2][2] = "...";这样的语句不会调用您的Proxy::operator=,它只会调用Proxy::operator[]。需要像m[2] = "...";这样的语句来调用Proxy::operator=,这在多维方案中是没有意义的。


此外,您的Matrix构造函数有错误-写入m[x]超出m[]数组的界限,因此数组实际上根本没有填充,并且您正在损坏周围的内存,泄漏内存。您需要写信给m[i]

//m[x] = new std::string[y];
m[i] = new std::string[y];

修复后,Matrix仍然,因为它没有实现析构函数来释放std::string。您必须delete[]new[](与deletenew相同)。

然后,您应该通过实现一个复制构造函数和一个复制赋值运算符(您的示例代码不需要它们,但生产代码应该始终具有它们)来完成对Rule of 3/5/0的支持,例如:

#include <iostream>
#include <string> 
#include <utility>

class Matrix {
    std::string **m;
    int m_x, m_y;
public:
    Matrix(int x = 0, int y = 0) : m_x(x), m_y(y) {
        m = new std::string*[x];
        for (int i = 0; i < x; ++i)
            m[i] = new std::string[y];
    }

    Matrix(const Matrix &src) : m_x(src.m_x), m_y(src.m_y) {
        m = new std::string*[m_x];
        for (int i = 0; i < m_x; ++i) {
            m[i] = new std::string[m_y];
            for (int j = 0; j < m_y; ++j) {
                m[i][j] = src.m[i][j];
            }
        }
    }

    ~Matrix() {
        for (int i = 0; i < m_x; ++i)
            delete[] m[i];
        delete[] m;
    }

    Matrix& operator=(const Matrix &rhs) {
        if (&rhs != this) {
            Matrix temp(rhs);
            std::swap(m, temp.m);
            std::swap(m_x, temp.m_x);
            std::swap(m_y, temp.m_y);
        }
        return *this;
    }
    
    class Proxy {
        std::string *mm;
    public:
        Proxy(std::string *s) : mm(s) {}

        std::string& operator[](int index) {
            return mm[index];
        }
    };

    Proxy operator[](int index) {
        return Proxy(m[index]);
    }
};

int main()
{
    Matrix m(5, 5);
 
    m[2][2] = "It Works";
    std::cout << m[2][2] << std::endl;
 
    Matrix m2(m);
    std::cout << m2[2][2] << std::endl;
 
    Matrix m3;
    m3 = m2;
    std::cout << m3[2][2] << std::endl;

    return 0;
}

Online Demo

但是,与其手动使用new[],不如考虑使用std::vector(您已经知道了,因为您的代码中有#include <vector>)。这样,3/5/0规则可以完全由编译器为您处理。std::vectorstd::string都完全符合规则,因此Matrix中的任何编译器生成的析构函数、复制构造函数和复制赋值操作符都将满足要求,例如:

#include <iostream>
#include <vector>
#include <string> 

class Matrix {
    std::vector<std::vector<std::string>> m;
public:
    Matrix(int x = 0, int y = 0) {
        m.resize(x);
        for (int i = 0; i < x; ++i)
            m[i].resize(y);
    }

    class Proxy {
        std::vector<std::string> &mm;
    public:
        Proxy(std::vector<std::string> &s) : mm(s) {}

        std::string& operator[](int index) {
            return mm[index];
        }
    };

    Proxy operator[](int index) {
        return Proxy(m[index]);
    }
};

Online Demo

这篇关于使用下标和等于运算符重载进行赋值和检索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆