我想要实现一个2D网格类,这是内存效率,因为它将用于蒙特卡罗模拟。然而,在这个阶段,这实际上与2D数组类相同。不用说,我是C++的新手。我写了以下代码。
#define MESH2D_H_INCLUDED
class Mesh2D
{
private:
double* mesh;
size_t rows;
size_t columns;
public:
/* constructor */
Mesh2D(size_t Nx, size_t Ny){
rows = Nx;
columns = Ny;
mesh = new double[Nx*Ny] {};
std::cout << "Mesh created." << std::endl;
}
/* destructor */
~Mesh2D()
{
delete[] mesh;
std::cout << "Mesh deleted." << std::endl;
}
/* accessors */
double getrows() const {return rows;}
double getcolumns() const {return columns;}
double& operator()(size_t i, size_t j)
{
if (i > rows || j > columns){
throw std::out_of_range("Index exceeds array bounds.");
}
return mesh[j + i*columns]; // row major access
}
/* copy constructor */
Mesh2D& operator=(const Mesh2D& rhs) // what is the difference between this line and the following? inline operator=(const Mesh2D& rhs)
{
if (rhs.rows != rows || rhs.columns != columns){
throw std::out_of_range("Assignment cannot be performed, mesh dimensions do not agree.");
}
mesh = new double [rows*columns];
// I want to avoid using a for loop
// for (int i=0; i<rows*columns; i++){
// mesh[i] = rhs.mesh[i];
// }
// Use this instead
memcpy(mesh, rhs.mesh, sizeof(rhs)); //however the output is not the expected.
std::cout << "copied!" << std::endl;
}
};
#endif // MESH2D_H_INCLUDED//MAIN FUNCTION
#include <iostream>
#include "Mesh2D.h"
void PrintMesh2D(Mesh2D &mesh){ //why isn't it going to work if I add const? I mean: void PrintMesh2D(const Mesh2D &mesh)
for (int i=0; i<mesh.getrows(); i++){
for (int j=0; j<mesh.getcolumns(); j++){
std::cout << mesh(i,j) << " ";
}
std::cout << std::endl;
}
}
int main()
{
Mesh2D mesh{3,3};
Mesh2D newmesh{3,3};
for (int i=0; i<mesh.getrows(); i++){
for (int j=0; j<mesh.getcolumns(); j++){
mesh(i,j) = j + i * mesh.getcolumns();
}
}
newmesh = mesh;
PrintMesh2D(newmesh);
}

我的问题是作为评论写的,但我在这里也列出了它们:
复制构造函数内部的inline operator=(const Mesh2D& rhs)
Mesh2D& operator=(const Mesh2D& rhs)和此行Mesh2D& operator=(const Mesh2D& rhs)之间的区别是什么?主函数内部的void PrintMesh2D(const Mesh2D &mesh)
欢迎你给我任何建议。由于我是C++新手,我有一种感觉,我正在编写错误的buggy代码。
编辑:
我以复制构造函数的形式编写了以下内容。
/* copy constructor */
Mesh2D (const Mesh2D& rhs)
{
rows = rhs.rows;
columns = rhs.columns;
mesh = new double[rows*columns];
memcpy(mesh,rhs.mesh,rows*columns*sizeof(double));
std::cout << "Copied!" << std::endl;
} 看上去对吗?
发布于 2020-07-03 08:23:49
我将尝试将缺失的部分添加到代码中:
在下面的代码之后,我将评论:
#include <iostream>
#include <cstring>
#include <algorithm>
class Mesh2D
{
private:
size_t rows;
size_t columns;
double* mesh;
public:
Mesh2D(size_t Nx, size_t Ny) : rows(Nx), columns(Ny), mesh(new double[Nx*Ny]{})
{
std::cout << "Mesh created." << std::endl;
}
Mesh2D(const Mesh2D& rhs) : rows(rhs.rows), columns(rhs.columns),
mesh(new double[rhs.rows * rhs.columns])
{
memcpy(mesh, rhs.mesh, (rhs.rows * rhs.columns) * sizeof(double));
// or better yet
// std::copy(rhs.mesh, rhs.mesh + rhs.rows * rhs.columns, mesh);
}
Mesh2D& operator=(const Mesh2D& rhs)
{
if ( &rhs != this )
{
Mesh2D temp(rhs);
std::swap(temp.rows, rows);
std::swap(temp.columns, columns);
std::swap(temp.mesh, mesh);
}
return *this;
}
~Mesh2D()
{
delete[] mesh;
std::cout << "Mesh deleted." << std::endl;
}
double getrows() const {return rows;}
double getcolumns() const {return columns;}
double& operator()(size_t i, size_t j)
{
if (i > rows || j > columns){
throw std::out_of_range("Index exceeds array bounds.");
}
return mesh[j + i*columns]; // row major access
}
double& operator()(size_t i, size_t j) const
{
if (i > rows || j > columns){
throw std::out_of_range("Index exceeds array bounds.");
}
return mesh[j + i*columns]; // row major access
}
};首先,注意使用成员初始化列表初始化Mesh2D类的成员。这样做是一个好习惯,而不是在构造函数的主体内分配。
第二,注意赋值操作符。它使用copy / swap idiom安全、干净地释放旧内存并复制。
第三,operator()应该有一个const重载,否则您就永远不能在这样的事情中使用类:
void foo(const Mesh2D& m)
{
std::cout << m(0,0);
}原因是m是const引用,因此只能在其上调用const函数。因此,operator()需要一个const版本,以及非const版本。
此外,operator()的非const版本也需要存在的原因是您可能希望这样做:
void foo2(Mesh2D& m)
{
m(0,0) = 23;
}如果m只有const版本的operator(),则由于operator()更改对象的内部状态,无法执行上述操作。
另一个问题是您使用memcpy不正确。memcpy工作在字节数上,而不是数组中的项目数。因此,您需要被sizeof(double)乘以,因为这是要复制的字节计数。更安全的解决方案是使用std::copy,它使用项目数自动使用正确的复制函数。
最后,错误的"Mesh2D“测试已经从赋值操作符中删除。原因是赋值操作符(和复制构造函数)作业是一回事,只有一件事--复制副本。
当您开始在副本分配函数中引入业务逻辑时,您就有可能创建不是副本的副本,而是正在传递的对象的伪副本。
这导致了C++中一些最讨厌和最难找到的bug,也就是当您的复制分配函数想玩游戏而不是真正复制的时候。如果您的复制构造函数或赋值操作符基于传递的值做出太多的决策和执行逻辑,那么您知道什么时候做错了什么。
为了完成,这里是类的相同版本,但使用std::vector<double>。请注意,由于不需要用户定义的赋值操作符、复制构造函数或析构函数,代码有多小:
#include <iostream>
#include <vector>
class Mesh2D
{
private:
size_t rows;
size_t columns;
std::vector<double> mesh;
public:
Mesh2D(size_t Nx, size_t Ny) : rows(Nx), columns(Ny), mesh(Nx*Ny)
{
std::cout << "Mesh created." << std::endl;
}
double getrows() const {return rows;}
double getcolumns() const {return columns;}
double& operator()(size_t i, size_t j)
{
if (i > rows || j > columns){
throw std::out_of_range("Index exceeds array bounds.");
}
return mesh[j + i*columns];
}
const double& operator()(size_t i, size_t j) const
{
if (i > rows || j > columns) {
throw std::out_of_range("Index exceeds array bounds.");
}
return mesh[j + i*columns];
}
};发布于 2020-07-03 07:33:11
inline operator=(const Mesh2D& rhs)是语法错误,它错过了返回类型。另外,Mesh2D(const Mesh2D& rhs).Mesh2D& operator=(const Mesh2D& rhs),但最后一个参数应该是正确的rows*colums*sizeof(double)大小,因此Mesh2D& operator=(const Mesh2D& rhs)是复制赋值操作符,而不是复制构造函数。sizeof(rhs)是类对象的大小,它与数组大小无关。由于您是在复制赋值操作符中而不是在复制构造函数中,所以mesh的内存已经被分配了,所以您应该从复制赋值操作符中删除mesh = new double [rows*columns];。您还必须在那里做一个与返回type.return *this;,然后您需要函子的const版本:double operator()(size_t i, size_t j) const下面是一个完整的示例:https://ideone.com/seOSwN
https://stackoverflow.com/questions/62710399
复制相似问题