1

我正在计算通过管道的边界层流动的属性。我有一个 CChannel 类,它存储管道的几何形状,CFlow 保存流体的全局属性,CNode 存储边界层的局部参数。当我以当前形式执行程序时,CChannel 内的 GridPoints 向量(变量“alpha”)的第一个元素被分配了与 Uinf 相同的内存位置,Uinf 是 CFlow 类的私有成员。当我更改后一个类以使其包含的字段不再是指针而是常规变量时,问题就消失了。我还尝试在类构造函数中为 GridPoints 向量保留内存空间,但没有任何效果。当我在寻找答案时,我发现这可能是由内置代码优化器引起的,但没有设法学习其他任何东西。(如果是这样,我怎样才能在不损失效率的情况下解决这个问题?)我猜测问题的出现是因为两种不同的内存分配模式(堆与堆栈)之间的差异。我仍然想知道为什么会发生这种情况,这样我就可以将全局流参数存储为指针,并在将来避免这个问题。

程序.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);
}

节点.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

};

节点.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.);
}

流.h

#pragma once
class CFlow
{
private:
    double *Uinf, *niu, *ro;
public:
    CFlow(double, double, double);
    ~CFlow(void);
};

流.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)
{}

频道.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
};

频道.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
}
4

2 回答 2

1

如前所述,您不需要所有这些指针 - 将它们更改为原始变量。

如果有一天您遇到需要指针的情况,请记住三法则:三法则是什么?.

您没有在类中定义复制构造函数和赋值运算符,就违反了这条规则,就像在这个特定的类中一样:

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;  
};
于 2012-10-27T19:48:51.747 回答
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++ 逗号运算符以了解原因。

于 2012-10-27T19:52:56.253 回答