【发布时间】:2011-09-30 09:12:16
【问题描述】:
我在 Class3 的对象中处理元素时遇到麻烦,请查看这个简化的类:
class Class1 {
public:
std::vector<Class2> c2v;
Class1();
};
class Class2 {
Class1 *instance;
int id;
public:
std::vector<Class3> c3v;
Class2 ( Class1 *instance, int id );
};
class Class3 {
Class1 *instance;
int id;
public:
Class3 ( Class1 *instance, int id );
};
及其构造函数:
Class1::Class1()
{
for ( int i = 0; i < noi; ++i ) {
c2v.push_back ( Class2 ( this, i ) );
}
}
Class2::Class2 ( Class1 *instance, int id )
{
this->instance = instance;
this->id = id;
for ( int k = 0; k < nok; ++k ) {
c3v.push_back ( Class3 ( this->instance, k ) );
}
}
在 main() 中,Class1 的对象使用其默认构造函数进行实例化。因此它创建了一个向量 c2v 并用 Class2 的“noi”对象填充它。
同时,当 Class2 的对象被放入 c2v 向量时,它们会被实例化,并且每个都创建一个向量 c3v 并用 Class3 的“非”对象填充它。
代码编译良好,但在运行时从 Class3 对象(通过this->instance->c2v[0].getSomeAttribute())访问 Class2 的公共属性时,程序会以 EXC_BAD_ACCESS 停止。
使用调试器检查表明指向c2v[0] 的指针已损坏(其值变为0x0)。
我是 C++ 的新手,我想知道尝试以这种方式实例化向量时会出现什么错误。我应该只声明向量并在 Class2 和 Class3 的所有实例创建完成后调用的单独函数中填充它们吗?
我正在添加一些实际代码,希望阅读不会太长(请理解我省略了一些前向声明和预处理器指令):
// global variables
extern char *filename; //not used
extern int nodes;
extern int numProdotti;
extern int classe; //not used
extern int maxNumRange; //not used
extern int *numRanges;
extern int *list ;
extern int *typeProdMarket;
extern int totalQtyDemand; //not used
extern int totNumRanges; //not used
extern struct product {
int qty;
int cost;
} **prodMarket;
extern struct range {
int discount;
int startOfRange;
} **rangeMarket; //not used
int main ( int argc, char *argv[] )
{
Ctqd instance;
instance.runOpt();
}
class Ctqd {
void greedySimple();
void greedySimpleReverse();
void greedyFromY();
void greedyByNiceness1();
void greedyByNiceness2();
void greedyByStepTier1();
void greedyByStepTier2();
void randomLocalSearch1();
void LocalSearch2opt();
public:
std::vector<Item> items;
std::vector<Supplier> suppliers;
Solution *solution;
Ctqd();
~Ctqd();
void runOpt();
};
class Supplier {
Ctqd *instance;
int id;
int refTotQty;
int refDiscount;
int refDiscountTier;
double refTotPrice;
double refUnitPrice;
double niceness;
int purTotQty;
int purDiscount;
int purDiscountTier;
public:
std::vector<Offer> offers;
Supplier ( Ctqd *instance, int id );
int getId();
int getRefTotQty();
int getRefDiscount();
int getRefDiscountTier();
double getRefTotPrice();
double getRefUnitPrice();
double getNiceness();
int getPurTotQty();
int getPurDiscount();
int getPurDiscountTier();
void updateStats();
};
class Offer {
Supplier *supplier;
int id;
int refQty;
double refPrice;
double niceness;
int purQty;
public:
Offer ( Supplier *supplier, int id );
int getId();
int getRefQty();
double getRefPrice();
double getNiceness();
int getPurQty();
void setPurQty ( int qty );
int remainingQty();
};
Ctqd::Ctqd()
{
// constructing items vector
for ( int k = 0; k < numProdotti; ++k ) {
items.push_back ( Item ( this, k ) );
}
// constructing suppliers vector
for ( int i = 0; i < nodes; ++i ) {
suppliers.push_back ( Supplier ( this, i ) );
}
// building solution
solution = new Solution ( this );
}
Supplier::Supplier ( Ctqd *instance, int id )
{
this->instance = instance;
this->id = id;
// computing total reference quantity
refTotQty = 0;
for ( int k = 0; k < numProdotti ; ++k ) {
refTotQty += std::min ( list[ k ] , prodMarket[ this->id ][ k ].qty );
}
// computing reference discount coefficients
refDiscount = 0;
refDiscountTier = 0;
for ( int r = 0; r < numRanges[ this->id ]; ++r ) {
if ( refTotQty < rangeMarket[ this->id ][ r ].startOfRange ) {
break;
}
else {
refDiscount = rangeMarket[ this->id ][ r ].discount;
refDiscountTier = r;
}
}
//computing total reference price
refTotPrice = 0;
for ( int k = 0; k < numProdotti ; ++k ) {
refTotPrice += prodMarket[ this->id ][ k ].cost * std::min ( list[ k ] , prodMarket[ this->id ][ k ].qty );
}
refTotPrice = refTotPrice * ( 1.000 - refDiscount / 100.000 );
//computing reference unit price
refUnitPrice = refTotPrice / refTotQty;
//computing supplier niceness
niceness = refTotQty / refUnitPrice;
purTotQty = 0;
purDiscount = 0;
purDiscountTier = 0;
// building offers vector
for ( int k = 0; k < numProdotti; ++k ) {
offers.push_back ( Offer ( this, k ) );
}
}
Offer::Offer ( Supplier *supplier, int id )
{
this->supplier = supplier;
this->id = id;
// computing reference quantity
refQty = std::min ( list[ this->id ] , prodMarket[ this->supplier->getId() ][ this->id ].qty );
// computing reference price
refPrice = prodMarket[ this->supplier->getId() ][ this->id ].cost * ( 1.000 - this->supplier->getRefDiscount() / 100.000 );
// computing niceness of the offer
niceness = refQty / ( ( prodMarket[ this->supplier->getId() ][ this->id ].cost + refPrice ) / 2 );
// init purQty to 0
purQty = 0;
}
这是我获得 EXC_BAD_ACCESS 的地方:
int Offer::remainingQty()
{
return prodMarket[ supplier->getId() ][ id ].qty - purQty;
}
我做了一些实验: 将 Ctqd 类和 Supplier 类中的向量更改为指向对象的向量。 问题仅部分解决。 构造 offer 对象时仍然有 EXC_BAD_ACCESS。
Offer 类的构造函数需要来自创建它的 Supplier 对象的数据。 我认为在仍在填充供应商向量时访问该数据可能会导致问题,因此我在供应商中创建了一个小初始化()函数:
void Supplier::initialize()
{
// constructing offers vector
for ( int k = 0; k < numProdotti; ++k ) {
offers.push_back ( new Offer ( this->instance, id, k ) );
}
}
并在 Ctqd 类构造函数的末尾添加了这个:
// init newly built objects
for ( int i = 0; i < nodes; ++i ) {
suppliers[i]->initialize();
}
现在似乎一切正常。但是我还是没有弄清楚到底是什么问题。
【问题讨论】:
-
您真正想做什么?指针所有权的政策是什么?
-
Class1 只是问题实例的容器。 Class2 代表我可以从中购买商品的供应商。 Class3 代表供应商对商品的报价。因此,我将所有供应商放在数组 c2v 中,每个供应商创建自己的 c3v 数组并用它的报价填充它。指针所有权都是公开的。
-
这个例子对我有用。您应该发布一个给出错误的完整可编译示例。
-
您可能正在复制
Class1的实例,而没有更新包含的Class2和Class3实例中的实例指针。 -
显示导致错误的实际代码。
标签: c++ vector nested instantiation