使用下标和等于运算符重载的赋值和检索
Assignment and retrieval using subscript and equals operator overloads
我一直在努力解决这个问题。我想要做的是使用运算符重载,以便我的对象表现得更像一个多维数组。我已经找到了解决实现这一目标所涉及的几个较小问题的解决方案,但每当我尝试将它们放在一起时,就会出现一个或另一个问题,要么是左值分配错误,要么是右值初始化无效,要么就是直接段错误。如果有任何建议,我将不胜感激。
#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;
}
否则,您的示例中并不真正需要指针,例如:
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
return 0;
}
无论哪种方式,您的 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[]
的东西(与 delete
和 new
相同)。
然后,您应该通过实现复制构造函数和复制赋值运算符来完成对 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;
}
但是,与其手动使用 new[]
,不如考虑使用 std::vector
(您已经知道,因为您的代码中有 #include <vector>
)。这样,3/5/0 规则可以完全由编译器为您处理。 std::vector
和 std::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]);
}
};
我一直在努力解决这个问题。我想要做的是使用运算符重载,以便我的对象表现得更像一个多维数组。我已经找到了解决实现这一目标所涉及的几个较小问题的解决方案,但每当我尝试将它们放在一起时,就会出现一个或另一个问题,要么是左值分配错误,要么是右值初始化无效,要么就是直接段错误。如果有任何建议,我将不胜感激。
#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;
}
否则,您的示例中并不真正需要指针,例如:
int main()
{
Matrix m(5, 5);
m[2][2] = "It Works";
std::cout << m[2][2] << std::endl;
return 0;
}
无论哪种方式,您的 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[]
的东西(与 delete
和 new
相同)。
然后,您应该通过实现复制构造函数和复制赋值运算符来完成对 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;
}
但是,与其手动使用 new[]
,不如考虑使用 std::vector
(您已经知道,因为您的代码中有 #include <vector>
)。这样,3/5/0 规则可以完全由编译器为您处理。 std::vector
和 std::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]);
}
};