【发布时间】:2018-06-16 04:20:55
【问题描述】:
为什么移动赋值运算符的这个实现会在附图中给出错误
Spreadsheet::Spreadsheet(Spreadsheet&& src) noexcept :Spreadsheet(src.width, src.height) {
this->cells = src.cells; // Shallow copy of data
src.cells = nullptr; src.width = 0; src.height = 0; // Reset the source object, because ownership has been moved!
};
Spreadsheet& Spreadsheet::operator=(Spreadsheet&& rhs) noexcept {
if (this == &rhs) return *this;
for (size_t i = 0; i < width; i++) delete[] cells[i];
delete[] cells;
this->width = rhs.width; this->height = rhs.height;
this->cells = rhs.cells;
rhs.cells = nullptr; rhs.width = 0; rhs.height = 0;
return *this;
};
我附上了全部资源。
电子表格类定义 电子表格.h
#pragma once
#include "SpreadsheetCell.h"
class Spreadsheet
{
public:
Spreadsheet(size_t, size_t);
~Spreadsheet();//1
void setCellAt(size_t, size_t, const SpreadsheetCell&);
void verifyCoordinate(size_t, size_t) const;
void swap(Spreadsheet);
SpreadsheetCell& getCellAt(size_t, size_t);
Spreadsheet(const Spreadsheet&); //copy constructor 2
Spreadsheet& operator=(const Spreadsheet& rhs); //assignment operator 3
Spreadsheet(Spreadsheet&& src) noexcept; // Move constructor 4
Spreadsheet& operator=(Spreadsheet&& rhs) noexcept; // Move assign 5
private:
size_t width = 0;
size_t height = 0;
SpreadsheetCell** cells = nullptr;
};
电子表格类实现 电子表格.cpp
#include "stdafx.h"
#include "Spreadsheet.h"
#include<utility>
Spreadsheet::Spreadsheet(size_t width, size_t height) :width(width), height(height)
{
cells = new SpreadsheetCell*[width];
for (size_t i = 0; i < height; i++) cells[i] = new SpreadsheetCell[height];
}
void Spreadsheet::verifyCoordinate(size_t x, size_t y) const
{
(x >= width || y >= height) ? throw std::out_of_range("") : void();// void();
}
void Spreadsheet::setCellAt(size_t x, size_t y, const SpreadsheetCell& cell)
{
verifyCoordinate(x, y);
cells[x][y] = cell;
}
SpreadsheetCell& Spreadsheet::getCellAt(size_t x, size_t y) {
verifyCoordinate(x, y);
return cells[x][y];
}
Spreadsheet::~Spreadsheet()
{
for (size_t i = 0; i < width; i++) {
delete[] cells[i];
};
delete[] cells;
cells = nullptr;
}
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];
}
void Spreadsheet::swap(Spreadsheet copyOfRhsDueToBassByVal) {
std::swap(copyOfRhsDueToBassByVal.width, this->width);
std::swap(copyOfRhsDueToBassByVal.height, this->height);
std::swap(copyOfRhsDueToBassByVal.cells, this->cells);
}
Spreadsheet& Spreadsheet::operator=(const Spreadsheet &rhs) {
if (this == &rhs) return *this;//we cant use return rhs because it is const but the function header returnning a non-const;
swap(rhs); return *this;
}
Spreadsheet::Spreadsheet(Spreadsheet&& src) noexcept :Spreadsheet(src.width, src.height) {
this->cells = src.cells; // Shallow copy of data
src.cells = nullptr; src.width = 0; src.height = 0; // Reset the source object, because ownership has been moved!
};
Spreadsheet& Spreadsheet::operator=(Spreadsheet&& rhs) noexcept {
if (this == &rhs) return *this;
for (size_t i = 0; i < width; i++) delete[] cells[i];
delete[] cells;
this->width = rhs.width; this->height = rhs.height;
this->cells = rhs.cells;
rhs.cells = nullptr; rhs.width = 0; rhs.height = 0;
return *this;
};
SpreadsheetCell 类定义 SPreadsheetCell.h
#pragma once
#include <string>
#include <string_view>
#include<iostream>
using namespace std;
class SpreadsheetCell
{
public:
SpreadsheetCell() = default;
SpreadsheetCell(double initialValue);
SpreadsheetCell(std::string_view initialValue);
void setValue(double);
double getValue() const;
void setString(std::string_view);
string getString() const;
private:
string doubleToString(double) const;
double stringToDouble(std::string_view) const;
double value = 0;
};
SpreadsheetCell 类实现
Spreadsheetcell.cpp
#include "stdafx.h"
#include "SpreadSheetCell.h"
SpreadsheetCell::SpreadsheetCell(double value) :value(value) {};
SpreadsheetCell::SpreadsheetCell(std::string_view strv) { value = stringToDouble(strv); };
void SpreadsheetCell::setValue(double value) { this->value = value; };
double SpreadsheetCell::getValue() const { return value; };
void SpreadsheetCell::setString(std::string_view str) { value = stringToDouble(str); };
string SpreadsheetCell::getString() const { return doubleToString(value); };
string SpreadsheetCell::doubleToString(double inValue) const {
return to_string(inValue);
}
double SpreadsheetCell::stringToDouble(string_view strv) const {
return strtod(strv.data(), nullptr);
}
【问题讨论】:
-
应该
delete[] cells[i];是delete cells[i]吗?在没有完整来源的情况下,这对我来说是最可疑的行。 -
@Stephano NO 单元格 def 是
cells = new SpreadsheetCell*[width]; for (size_t i = 0; i < height; i++) cells[i] = new SpreadsheetCell[height];而且资源很长,在提供移动构造函数和赋值运算符之前代码运行良好 -
我们需要查看
cells的任何类型的声明。还有Spreadsheet中cells成员的声明。请不要让我们玩猜谜游戏。 -
@PaulSanders 单元格是
SpreadsheetCell类型的指针,这是 Spreadsheet.h 中的声明SpreadsheetCell** cells = nullptr; -
@AsmM 那个循环是错误的。它应该使用
i < width而不是i < height。
标签: c++ constructor move-semantics move-constructor