我正在计算通过风管的边界层流的属性。我有一个类CChannel,它存储管道的几何形状,CFlow保存流体的全局属性,CNode存储边界层的局部参数。 当我以当前形式执行程序时,CChannel内的GridPoints向量的第一个元素(变量“alpha”)被赋予与Uinf相同的内存位置,Uinf是CFlow类的私有成员。当我改变后一类时,它所持有的字段不再是指针而是常规变量,问题就消失了。我也尝试在类构造函数中为GridPoints向量保留内存空间,但没有任何影响。当我在寻找答案时,我发现这可能是由内置代码优化器引起的,但却没有学到任何其他东西。 (如果是这样的话,我如何在不失效率的情况下解决这个问题?)我猜这个问题是由于两种不同的内存分配模式(堆与堆栈)之间的差异而产生的。我仍然想知道为什么会发生这种情况,所以我可以将全局流参数存储为指针并在将来避免这个问题。
Program.cpp
#include <iostream>
#include "Channel.h" // stores the channel geometry
#include "Flow.h" // stores the fluid properties and free stream data
#include "Node.h" // holds the local BL flow properties, e.g. BL thickness, lambda, etc.
using namespace std;
int main(void)
{
int NoNodes=21;
CChannel MyChan(4, 1.2, .8); // L, h1, h2
MyChan.MeshUniform(NoNodes);
CFlow Flow1(.5,1.529e-5,1.19); // Uinf, niu, ro
for (int i=0;i<NoNodes;i++)
{
MyChan.GridPoints->at(i).GetAlpha();
}
return(0);
}
Node.h
#pragma once
class CNode
{
public:
double *alpha, *x, *lambda; // properties dependent on the Pollhausen velocity profile
CNode(void);
~CNode(void);
void GetAlpha(void); // calculates alpha
};
Node.cpp
#include "Node.h"
#include <iostream>
CNode::CNode(void)
{
alpha=new double;
lambda=new double;
*lambda=0;
}
CNode::~CNode(void)
{
delete alpha, x, lambda;
}
void CNode::GetAlpha(void)
{
*alpha=(.3-*lambda/120.);
}
Flow.h
#pragma once
class CFlow
{
private:
double *Uinf, *niu, *ro;
public:
CFlow(double, double, double);
~CFlow(void);
};
Flow.cpp
#include "Flow.h"
CFlow::CFlow(double u, double visc, double den)
{
Uinf=new double;
niu=new double;
ro=new double;
*Uinf=u; // free stream velocity (assumes the inflow is parallel to the channel's CL) [m/s]
*niu=visc; // kinematic viscosity of the fluid [m^2/s]
*ro=den; // density of the fluid [kg/m^3]
}
CFlow::~CFlow(void)
{}
channel.h中
#pragma once
#include <vector>
#include "Node.h"
class CChannel
{
public:
double *L, *h1, *h2; // h1 & h2 defined from the CL => make use of the problem assumed to be symmetric
std::vector<CNode> *GridPoints; // stores data for each individual grid point
CChannel(double, double, double);
~CChannel(void);
void MeshUniform(int); // creates a uniform distribution of nodes along the length of the channel
};
Channel.cpp
#include "Channel.h"
CChannel::CChannel(double length,double height1,double height2)
{
L=new double; // allocate memory
h1=new double;
h2=new double;
GridPoints = new std::vector<CNode>;
*L=length; // assign input values
*h1=height1;
*h2=height2;
}
CChannel::~CChannel(void)
{
delete L, h1, h2, GridPoints; // delete all the members of the class
}
void CChannel::MeshUniform(int NoNodes)
{
GridPoints->resize(NoNodes); // resize the vector
double dx=*L/(NoNodes-1); // increment of length between each pair of nodes
for (int i=0; i<NoNodes; i++)
*GridPoints->at(i).x=0.+i*dx; // assign the location to each node
}
答案 0 :(得分:1)
如前所述,您不需要所有这些指针 - 将它们更改为原始变量。
如果你有一天会遇到需要指针的情况,那么请记住三条规则:What is The Rule of Three?。
你没有在类中定义复制构造函数和赋值运算符,就像在这个特定的类中一样,打破了这个规则:
class CNode
{
public:
double *alpha, *lambda; // properties dependent on the Pollhausen velocity profile
CNode(void);
~CNode(void);
void GetAlpha(void); // calculates alpha
};
您在CNode
中使用此std::vector<CNode>
- 因此,您正在错误地复制此CNode
个对象。
所以你需要添加复制构造函数和赋值运算符 - 那么即使你仍然使用指针,你的问题也应该消失,就像在这个简单的示例类中一样:
class Example {
public:
Example() : p(new int()) {}
~Example() { delete p; }
Example(const Example& e) p(new int(e.p?*e.p:0)) {}
Example& operator = (Example e)
{
std::swap(e.p, p);
return *this;
}
private:
int* p;
};
答案 1 :(得分:1)
它是编译的,但解释是在你的指针代码中你没有写出可以复制的对象(正如Piotr所说,你没有遵循三条规则)。由于这个错误,正在发生的事情是内存开始分配,内存被释放然后再次分配。通过重合再次分配内存时,它会重用刚刚释放的相同地址。这就是你看到相同指针值的原因。
MyChan.GridPoints->at(0).alpha
是一个指针,但它指向的内存已被释放。然后为Flow1.Uinf
分配更多内存,并重用MyChan.GridPoints->at(0).alpha
所指向的相同释放内存。所以你得到两个指针的相同值。
另一个误解你
delete L, h1, h2, GridPoints; // delete all the members of the class
不会删除该班级的所有成员。仅
delete L; // delete all the members of the class
delete h1;
delete h2;
delete GridPoints;
那样做。你写的只删除了GridPoints。您可能需要查找C ++逗号运算符以获取解释原因。