Vasu
Vasu

Reputation: 1110

All pushed back values in vector changing to default value

In an effort to reduce multiple functions (that were nearly identical) in my code, I decided to consolidate them all into one function which takes an additional parameter (a class with multiple parameters, actually), and then uses those values to imitate what the multiple functions would have done. Then, long story short, I put each of those class declarations into a vector, and now my program seems dysfunctional.

My multiple instances of a class:

FragmentCostParameters commonFCP = FragmentCostParameters(.05, 0);
FragmentCostParameters rareFCP = FragmentCostParameters(.05, 50);
FragmentCostParameters uniqueFCP = FragmentCostParameters(.05, 125);
FragmentCostParameters legendaryFCP = FragmentCostParameters(.02, 175);
FragmentCostParameters crystallineFCP = FragmentCostParameters(.02, 250);
FragmentCostParameters superEliteFCP = FragmentCostParameters(.02, 300);

Which get placed into a vector by:

vector<FragmentCostParameters> FCPs(6);

FCPs.push_back(FragmentCostParameters(.05, 0));
FCPs.push_back(FragmentCostParameters(.05, 50));
FCPs.push_back(FragmentCostParameters(.05, 125));
FCPs.push_back(FragmentCostParameters(.02, 175));
FCPs.push_back(FragmentCostParameters(.02, 250));
FCPs.push_back(FragmentCostParameters(.02, 300));

Additionally, that class is defined below:

class FragmentCostParameters {
public:
    double multFactor;
    double subtractFactor;
    FragmentCostParameters(double _multFactor, double _subtractFactor){
        multFactor = _multFactor;
        subtractFactor = _subtractFactor;
    }
    FragmentCostParameters(){
        multFactor = .05;
        subtractFactor = 0;
    }

};

Now, you'll notice that the default constructor for the FragmentCostParameters involves setting multFactor = .05 and subtractFactor = 0. However, it seems that no matter what I push back, each of the values in my vector become mutated into those values. At least, that's what VS 2011 tells me the values are equal to when I'm looking at them in a local scope in the following function (which is the only place they're used).

int FragmentCost(double skillLevel, int duration, FragmentCostParameters FCP){
    return max((int)(ceil(FCP.multFactor*(skillLevel-FCP.subtractFactor))*ceil(duration/30.0)) , 0);
}

And the only place that FragmentCost is called is from this function below, which is supposed to pass different values .. but somewhere in the process, when I look at locals in FragmentCost, they're always the default values in the constructor for the class.

//given a skill level + duration, will return an array with the fragment usage
int* regularTotalFragCost(int skillLevel, int duration){
    int fragments[7] = {0,0,0,0,0,0,0};
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[0]);
    fragments[1]+= FragmentCost(skillLevel,duration, FCPs[0]);
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[1]);
    fragments[2]+= FragmentCost(skillLevel,duration, FCPs[1]);
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[2]);
    fragments[3]+= FragmentCost(skillLevel,duration, FCPs[2]);
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[3]);
    fragments[4]+= FragmentCost(skillLevel,duration, FCPs[3]);
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[4]);
    fragments[5]+= FragmentCost(skillLevel,duration, FCPs[4]);
    fragments[0]+= FragmentCost(skillLevel,duration, FCPs[5]);  
    fragments[6]+= FragmentCost(skillLevel,duration, FCPs[5]);
    return fragments;
}

For some reason I feel that I'm making a really stupid mistake somewhere, but for the life of me I can't seem to figure it out. I would appreciate any help and/or advice anyone could offer.

EDIT: Here's what the values for fragments[] in regularTotalFragCost are supposed to be if everything is working correctly, using a couple test values (skillLevel = 250 and duration = 30)

FCPs[0] : Fragments: 13, 13, 0, 0, 0, 0, 0, 
FCPs[1] : Fragments: 17, 15, 2, 0, 0, 0, 0, 
FCPs[2] : Fragments: 20, 14, 5, 1, 0, 0, 0, 
FCPs[3] : Fragments: 29, 14, 9, 5, 1, 0, 0, 
FCPs[4] : Fragments: 32, 13, 10, 7, 2, 0, 0, 
FCPs[5] : Fragments: 32, 13, 10, 7, 2, 0, 0, 

And here is what they are as of right now:

FCPs[0] : Fragments: 78, 13, 13, 13, 13, 13, 13, 
FCPs[1] : Fragments: 78, 13, 13, 13, 13, 13, 13, 
FCPs[2] : Fragments: 78, 13, 13, 13, 13, 13, 13, 
FCPs[3] : Fragments: 78, 13, 13, 13, 13, 13, 13, 
FCPs[4] : Fragments: 78, 13, 13, 13, 13, 13, 13, 
FCPs[5] : Fragments: 78, 13, 13, 13, 13, 13, 13, 

Upvotes: 0

Views: 198

Answers (3)

Ben Voigt
Ben Voigt

Reputation: 283624

vector<FragmentCostParameters> FCPs(6);

creates a vector of 6 default-constructed values, numbered 0-5.

FCPs.push_back(FragmentCostParameters(.05, 0));

adds value at index 6

Upvotes: 4

Jesse Good
Jesse Good

Reputation: 52365

int fragments[7] is a local variable on the stack. Once that function returns, that memory is no longer valid. You are returning a pointer to that local variable and any access to that memory is undefined behavior.

Instead, return an std::array:

std::array<int, 7> fragments = {}; // value initialize

return fragments;

Upvotes: 3

Adam Burry
Adam Burry

Reputation: 1902

Hint: How big is your vector after you push_back your FCPs?

Upvotes: 0

Related Questions