gpt4 book ai didi

C++ 在类构造函数中填充 vector

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:34:18 25 4
gpt4 key购买 nike

我在寻址 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 的对象使用其默认构造函数实例化。因此它创建一个 vector c2v 并用 Class2 的“noi”对象填充它。

同时,当 Class2 的对象被放入 c2v vector 时,它们被实例化,每个创建一个 vector c3v 并用 Class3 的“非”对象填充它。

代码编译正常,但在运行时,当从 Class3 对象访问 Class2 的公共(public)属性时(通过 this->instance->c2v[0].getSomeAttribute()),程序停止并出现 EXC_BAD_ACCESS。

使用调试器检查显示指向 c2v[0] 的指针已损坏(其值变为 0x0)。

我是 C++ 的新手,我想知道尝试以这种方式实例化 vector 时会出现什么错误。我是否应该只声明 vector 并在创建完 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 类中的 vector 更改为指向对象的指针 vector 。问题只得到部分解决。构建优惠对象时仍然有 EXC_BAD_ACCESS。

Offer 类的构造函数需要来自创建它的 Supplier 对象的数据。我认为在供应商 vector 仍在填充时访问该数据可能会导致问题,因此我在供应商中创建了一个小的 initialize() 函数:

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();
}

现在看起来一切正常。但我仍然没有弄清楚问题到底是什么。

最佳答案

到目前为止,最简单(也是最好)的修复方法是使用 std::deque 而不是 std::vector。您不需要使用指针;你可以坚持原来的插入物体的计划。

使用双端队列,push_back 保证不会使对其元素的引用无效。实际上,push_front 也是如此。并且它仍然支持恒定时间随机访问 (foo[n])。

在增量构建装满对象的容器时,双端队列通常是您想要的。

一般来说,std::deque 可能是您从未使用过的最好的数据结构。

关于C++ 在类构造函数中填充 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7608256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com