代码中有几个逻辑错误:
-
分配构造函数没有正确地循环通过第一个维度数组。您正在使用
width
元素的数目,然后在其中循环
height
取而代之的是元素的数量。如果
width < height
,则超出数组的界限并损坏内存。如果
width > height
,则不填充整个数组,只留下不确定值的指针。
-
你的移动构造函数正在泄漏内存。它委托给分配构造函数而不是默认构造函数,因此分配了一个新数组,然后泄漏该数组。move构造函数根本不应该分配任何内容。
-
你的
swap()
没有正确交换。目的
SWAP()
是交换两个对象的内容,但输入参数是按值传递的,因此传递给它的任何对象都会先被复制,然后再与复制的对象交换,而不是与原始对象交换。原始对象不变。所以必须通过引用传递参数。
此外,move构造函数和move赋值运算符的一个典型且可取的实现是简单地交换moved to和moved from对象的内容。让moved from对象的析构函数释放任何旧资源。在移动新资源之前,不要浪费时间释放旧资源。
改为尝试类似的操作:
#pragma once
#include "SpreadsheetCell.h"
class Spreadsheet
{
public:
Spreadsheet() = default;
Spreadsheet(size_t, size_t);
Spreadsheet(const Spreadsheet &);
Spreadsheet(Spreadsheet &&) noexcept;
~Spreadsheet();
Spreadsheet& operator=(const Spreadsheet &);
Spreadsheet& operator=(Spreadsheet &&) noexcept;
SpreadsheetCell& getCellAt(size_t, size_t);
void setCellAt(size_t, size_t, const SpreadsheetCell&);
void swap(Spreadsheet &);
private:
size_t width = 0;
size_t height = 0;
SpreadsheetCell** cells = nullptr;
void verifyCoordinate(size_t, size_t) const;
};
void swap(Spreadsheet &lhs, Spreadsheet &rhs);
#include "stdafx.h"
#include "Spreadsheet.h"
#include <utility>
Spreadsheet::Spreadsheet() noexcept
: cells(nullptr), width(0), height(0)
{
}
Spreadsheet::Spreadsheet(int width, int height)
: cells(nullptr), width(width), height(height)
{
cells = new SpreadsheetCell*[width];
for (size_t i = 0; i < width; ++i)
cells[i] = new SpreadsheetCell[height];
}
Spreadsheet::Spreadsheet(const Spreadsheet &src)
: Spreadsheet(src.width, src.height)
{
for (size_t i = 0; i < width; ++i)
for (size_t j = 0; j < height; ++j)
cells[i][j] = src.cells[i][j];
}
Spreadsheet::Spreadsheet(Spreadsheet &&src) noexcept
: Spreadsheet()
{
src.swap(*this);
}
Spreadsheet::~Spreadsheet()
{
for (size_t i = 0; i < width; ++i)
delete[] cells[i];
delete[] cells;
}
Spreadsheet& Spreadsheet::operator=(const Spreadsheet &rhs)
{
if (this != &rhs)
Spreadsheet(rhs).swap(*this);
return *this;
}
Spreadsheet& Spreadsheet::operator=(Spreadsheet &&rhs) noexcept
{
rhs.swap(*this);
return *this;
}
SpreadsheetCell& Spreadsheet::getCellAt(size_t x, size_t y)
{
verifyCoordinate(x, y);
return cells[x][y];
}
void Spreadsheet::setCellAt(size_t x, size_t y, const SpreadsheetCell& cell)
{
verifyCoordinate(x, y);
cells[x][y] = cell;
}
void Spreadsheet::swap(Spreadsheet &other)
{
std::swap(cells, other.cells);
std::swap(width, other.width);
std::swap(height, other.height);
}
void Spreadsheet::verifyCoordinate(size_t x, size_t y) const
{
if (x >= width || y >= height)
throw std::out_of_range("");
}
void swap(Spreadsheet &lhs, Spreadsheet &rhs)
{
lhs.swap(rhs);
}
也就是说,如果使用
std::vector
而不是原始数组:
#pragma once
#include "SpreadsheetCell.h"
#include <vector>
class Spreadsheet
{
public:
Spreadsheet() = default;
Spreadsheet(size_t, size_t);
Spreadsheet(const Spreadsheet &) = default;
Spreadsheet(Spreadsheet &&) noexcept = default;
Spreadsheet& operator=(const Spreadsheet &) = default;
Spreadsheet& operator=(Spreadsheet &&) noexcept = default;
SpreadsheetCell& getCellAt(size_t, size_t);
void setCellAt(size_t, size_t, const SpreadsheetCell&);
void swap(Spreadsheet &);
private:
std::vector<std::vector<SpreadsheetCell>> cells;
};
void swap(Spreadsheet &lhs, Spreadsheet &rhs);
#include "stdafx.h"
#include "Spreadsheet.h"
#include <utility>
Spreadsheet::Spreadsheet(int width, int height)
{
cells.resize(width);
for (size_t i = 0; i < width; ++i)
cells[i].resize(height);
}
SpreadsheetCell& Spreadsheet::getCellAt(size_t x, size_t y)
{
return cells.at(x).at(y);
}
void Spreadsheet::setCellAt(size_t x, size_t y, const SpreadsheetCell& cell)
{
cells.at(x).at(y) = cell;
}
void Spreadsheet::swap(Spreadsheet &other)
{
std::swap(cells, other.cells);
}
void swap(Spreadsheet &lhs, Spreadsheet &rhs)
{
lhs.swap(rhs);
}