初始化和维护结构的结构 我编写C++代码来处理从实验室测量中提取的一组直方图。当我试图更好地组织事情时,我遇到了问题,我认为我的问题来自错误地处理指针和/或结构
我最初的设计是这样的:初始化和维护结构的结构 我编写C++代码来处理从实验室测量中提取的一组直方图。当我试图更好地组织事情时,我遇到了问题,我认为我的问题来自错误地处理指针和/或结构,c++,pointers,struct,C++,Pointers,Struct,我最初的设计是这样的: // the following are member variables Histogram *MassHistograms[3]; Histogram *MomentumHistograms[3]; Histogram *PositionHistograms[3]; 其中,每个阵列的元素0对应于一个实验室测量值,每个阵列的元素1对应于另一个,等等。我可以通过MassHistograms[0]或类似方式访问各个直方图,并且工作正常。然而,在我看来,这个组织并不合适。如
// the following are member variables
Histogram *MassHistograms[3];
Histogram *MomentumHistograms[3];
Histogram *PositionHistograms[3];
其中,每个阵列的元素0对应于一个实验室测量值,每个阵列的元素1对应于另一个,等等。我可以通过MassHistograms[0]
或类似方式访问各个直方图,并且工作正常。然而,在我看来,这个组织并不合适。如果我要执行一个新的度量,我必须在每个直方图数组中添加一个元素。相反,我想出了
struct Measurement {
Histogram *MassHistogram;
Histogram *MomentumHistogram;
Histogram *PositionHistogram;
};
作为增加复杂性的一层,我还想根据对数据的处理将这些测量捆绑起来,所以我
struct MeasurementSet {
Measurement SignalMeasurement;
Measurement BackgroundMeasurement;
};
我认为这种安排更具逻辑性和可扩展性,但它不起作用;-)如果我有这样的代码
MeasurementSet ms;
Measurement m = ms.SignalMeasurement;
Histogram *h = m.MassHistogram;
然后试着用h
,我发现了一个分段错误。由于类似的代码以前工作得很好,我假设我没有正确处理代码中的结构。具体来说,结构是否需要以任何方式显式初始化?(直方图由其他人的库提供,只需声明直方图*SomeHistograms[4]就足以对其进行初始化。)
我感谢你的反馈。我非常熟悉Python和Culjule,但是我对C++的有限知识并不延伸到[看起来和类似的]结构的照顾和喂养的奥秘:-)/P>
我最终做了什么 我把
Measurement
变成了一门全面的课程:
class Measurement {
Measurement() {
MassHistogram = new Histogram();
MomentumHistogram = new Histogram();
PositionHistogram = new Histogram();
};
~Measurement() {
delete MassHistogram;
delete MomentumHistogram;
delete PositionHistogram;
};
Histogram *MassHistogram;
Histogram *MomentumHistogram;
Histogram *PositionHistogram;
}
(我调用的通用的Histogram()
constructor工作得很好。)我遇到的另一个问题是通过总是通过引用传递度量值来解决的;否则,将在接收到测量值的任何函数结束时调用析构函数,并且下一次尝试使用其中一个直方图执行操作时将出错
谢谢大家的回答 当结构包含指针时,必须自己初始化该变量。
例子
您知道您的测量定义
没有为实际的直方图
分配内存吗?在您的代码中,m.MassHistogram
是一个悬空(未初始化)指针,它不指向任何测量的直方图,也不指向任何能够存储直方图的内存。正如@Nari Rennlos刚刚发布的,您需要将其指向现有(或新分配的)直方图
您的第三方库的界面是什么样子的?如果可能的话,您应该有一个度量
包含3个直方图
s(而不是指向直方图
s的3个指针)。这样,当您创建度量值
或度量值集
时,将为您创建相应的直方图
s,销毁时也是如此。如果仍然需要指针,可以使用&
运算符:
struct Measurement2 {
Histogram MassHistogram;
Histogram MomentumHistogram;
Histogram PositionHistogram;
};
MeasurementSet2 ms;
Histogram *h = &ms.SignalMeasurement.MassHistogram; //h valid as long as ms lives
还请注意,只要不使用指针(或引用),对象将被复制并按值赋值:
MeasurementSet ms; //6 uninitialized pointers to Histograms
Measurement m = ms.SignalMeasurement; //3 more pointers, values taken from first 3 above
Histogram *h = m.MassHistogram; //one more pointer, same uninitialized value
虽然如果指针已经初始化,那么此时所有10个指针都将指向实际的直方图
如果有实际的成员而不是指针,情况会变得更糟:
MeasurementSet2 ms; //6 Histograms
Measurement2 m = ms.SignalMeasurement; //3 more Histograms, copies of first 3 above
Histogram h = m.MassHistogram; //one more Histogram
h.firstPoint = 42;
m.MassHistogram.firstPoint = 43;
ms.SignalMeasurement.MassHistogram.firstPoint = 44;
…现在有3个稍有不同的质量信号直方图,2对相同的动量和位置信号直方图,以及三组背景直方图 您确定直方图*某些直方图[4]
初始化了数据吗?如何填充直方图结构
这里的问题与其说是结构,不如说是让你绊倒的指针。执行此操作时:MeasurementSet ms代码>它声明MeasurementSet类型的“自动变量”。这意味着MeasurementSet的所有内存都已“分配”并准备就绪。MeasurementSet又有两个类型为Measurement的变量,它们也是“已分配”和“准备就绪”。反过来,度量有3个直方图*类型的变量,它们也是“已分配”和“准备就绪”。。。但是等等!“直方图*”类型是一个“指针”。这意味着它是一个地址——一个描述实际内存位置的32或64位(或任意位)值。就这样。这取决于你如何指向某个东西——在那个位置放置某个东西。在它指向任何东西之前,它实际上会包含随机数据(或者0'd out数据,或者一些特殊的调试数据,或者类似的数据)——关键是如果你试图用它做一些事情,你会得到一个分段错误,因为你可能会试图读取你的程序不应该读取的部分数据
<>在C++中,结构与一个类(在Python中有类似的概念)几乎完全相同,并且通常分配一个类似于:
m.MassHistogram = new Histogram();
…之后,柱状图就可以开始了。然而,YMMV:你能自己分配一个吗?或者你只能从某个库中获得一个,可能是从设备读取,等等?此外,虽然你可以做我写的,但它不一定“漂亮”。c++-ic解决方案是将分配放在构造函数(如python中的init)中,并将删除放在析构函数中。首先,请始终记住,结构和类几乎完全相同。唯一的区别是结构成员在默认情况下是公共的,而类成员在默认情况下是私有的。
但其余的都是一样的
其次,仔细区分指针和对象
如果我写
Histogram* h;
Histogram* h = new Histogram();
Histogram* copy = h;
Histogram* h = new Historgram;
Histogram* copy = h;
delete h;
直方图h代码>
将为直方图的数据分配空间,并调用其构造函数。(构造是一个与类名称完全相同的方法,这里是Historgr
Histogram* h = new Historgram;
Histogram* copy = h;
delete h;