I have the following functor:
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
It is supposed to be a strict weak ordering, and it's this long (could be one line only) for debug purposes.
I'm using this functor as a comparator functor for a stl::set. Problem being, it only inserts the first element. By adding console output to the comparator function, I learned that it's actually comparing the file name to itself every time.
Other relevant lines are:
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
and
// (FileSet files_;) <- SimulatedDisk private class member
void SimulatedDisk::addFile(SimulatedDiskFile * file) {
files_.insert(file);
positions_calculated_ = false;
}
EDIT: the code that calls .addFile() is:
current_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
current_request++;
}
Where all_requests is a list, and class Request is such that:
class Request {
private:
string file_name_;
int response_code_;
int response_size_;
public:
void setFileName(string file_name);
string getFileName();
void setResponseCode(int response_code);
int getResponseCode();
void setResponseSize(int response_size);
int getResponseSize();
};
I wish I could offer my hypotesis as to what's going on, but I actually have no idea. Thanks in advance for any pointers.
There's nothing wrong with the code you've posted, functionally speaking. Here's a complete test program - I've only filled in the blanks, not changing your code at all.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class SimulatedDiskFile
{
public:
string getFileName() { return name; }
SimulatedDiskFile(const string &n)
: name(n) { }
string name;
};
class ComparatorClass {
public:
bool operator () (SimulatedDiskFile * file_1, SimulatedDiskFile * file_2) {
string file_1_name = file_1->getFileName();
string file_2_name = file_2->getFileName();
cout << file_1_name << " and " << file_2_name << ": ";
if (file_1_name < file_2_name) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
};
typedef set<SimulatedDiskFile *, ComparatorClass> FileSet;
int main()
{
FileSet files;
files.insert(new SimulatedDiskFile("a"));
files.insert(new SimulatedDiskFile("z"));
files.insert(new SimulatedDiskFile("m"));
FileSet::iterator f;
for (f = files.begin(); f != files.end(); f++)
cout << (*f)->name << std::endl;
return 0;
}
I get this output:
z and a: false
a and z: true
z and a: false
m and a: false
m and z: true
z and m: false
a and m: true
m and a: false
a
m
z
Note that the set ends up with all three things stored in it, and your comparison logging shows sensible behaviour.
Edit:
Your bug is in these line:
SimulatedDiskFile temp_file(current_request->getFileName(), current_request->getResponseSize());
disk.addFile(&temp_file);
You're taking the address of a local object. Each time around the loop that object is destroyed and the next object is allocated into exactly the same space. So only the final object still exists at the end of the loop and you've added multiple pointers to that same object. Outside the loop, all bets are off because now none of the objects exist.
Either allocate each SimulatedDiskFile with new (like in my test, but then you'll have to figure out when to delete them), or else don't use pointers at all (far easier if it fits the constraints of your problem).
And here is the problem:
SimulatedDiskFile temp_file(current_request->getFileName(),
current_request->getResponseSize());
disk.addFile(&temp_file);
You are adding a pointer to a variable which is immediately destroyed. You need to dynamically create your SDF objects.
urrent_request = all_requests.begin();
while (current_request != all_requests.end()) {
SimulatedDiskFile temp_file(...blah..blah..); ====> pointer to local variable is inserted
disk.addFile(&temp_file);
current_request++;
}
temp_file would go out of scope the moment next iteration in while loop. You need to change the insert code. Create SimulatedDiskFile objects on heap and push otherwise if the objects are smaller then store by value in set.
Agree with #Earwicker. All looks good. Have you had a look inside all_requests? Maybe all the filenames are the same in there and everything else is working fine? (just thinking out loud here)
Related
I'm trying to return values in a struct after certain conditions the values are initialised as zero but for some reason they don't increment when the condition is met. I'm brand new to c++ and VS so haven't quite got a grip of how to use the debugger properly. I have checked that the values do in fact initialise to zero. I'm assuming the problem must stem from the input to the SubmitGuess method which should take in a string but must not be for some reason failing that the if statements must be incorrect. Sorry my code is riddled with commented out code, comments and is not complete so please ignore that there is code that should be moved or removed etc. Any help would be greatly appreciated and apologies for posting so much code thought it would be easier to just show you rather than trying to explain.
I should also explain I'm using UE4's recommended data types so whenever you see FString it's just a string same with int32 just an int
#include "FISOGame.h"
#include <iostream>
using int32 = int;
//constructor
FGame::FGame()
{
//initialising the private variables so they don't return with an error
//MyCurrentTries = 1;
//MaxTries = 3;
Reset();
}
void FGame::Reset()
{
MyCurrentTries = 1;
MaxTries = 7;
const FString MyHiddenWord = "cat";
return;
}
int FGame::GetMaxTries() const
{
return MaxTries; // gets private variable from header file and returns it
}
int FGame::GetCurrentTries() const
{
return MyCurrentTries;
}
bool FGame::IsGameWon() const
{
// TODO check if game is won
return false;
}
bool FGame::CheckGuessValidity(FString)
{
// TODO check if guess makes sense
return false;
}
// recieves a valid guess, increments turn and returns count
BullCowCount FGame::SubmitGuess(FString Guess)
{
// increment the turn number
MyCurrentTries++;
// setup a return value
BullCowCount BullCowCount;
// get length of hidden word
int32 HiddenWordLength = MyHiddenWord.length();
//loop through all letters of the guess
//compare letters against hidden word
// if they match then
//increment bulls if there in the same place
// increment cows id not
FString Attempt = Guess;
for (int32 MHWChar = 0; MHWChar < HiddenWordLength; MHWChar++) {
for (int32 GChar = 0; GChar < HiddenWordLength; GChar++) {
if (Attempt[GChar] == MyHiddenWord[MHWChar]) {
if (MHWChar == GChar) {
BullCowCount.Bulls++;
}
else {
BullCowCount.Cows++;
}
}
}
}
return BullCowCount;
}
#pragma once
#include <string>
using FString = std::string;
using int32 = int;
//never use using namespace in header file
//struct same as class only variables are defaulted public
// variables initialised to 0
struct BullCowCount {
int32 Bulls = 0;
int32 Cows = 0;
};
class FGame {
public:
//constructor make by reusing class name
// when create instance of class it looks for a constructor and runs whatevers in it
FGame();
public:
int32 GetMaxTries() const; // const if you don't want the method to change anything
int32 GetCurrentTries() const;
void Reset();
bool IsGameWon() const;
bool CheckGuessValidity(FString);
// TODO create method fro counting bulls and cows and increasing turn number
BullCowCount SubmitGuess(FString);
private:
// have to initialise the value to avoid error as it's not been created add comment and recompile to get actual value
// it doesn't pick up the change in the compiler
//see constructor for initialisation
int32 MyCurrentTries;
int32 MaxTries;
FString MyHiddenWord;
};
#include <iostream>
#include <string>
#include "FISOGame.h"
using FText = std::string;
using int32 = int;
//using namespace std; // Don't use using namespace as it makes it difficult to see whats included
// create reference or call for function Game_Ask above the main function or wherever it is called
// must put data type for original function before call this makes it a reference and loads it in to memory first
// same thing as declaring functions in a header file
void Game_Intro();
FText Game_Guess();
void Game_loop();
// make game instance doing this at the top so that it's global and can be accessed by all the functions
// then you can call this instance (NewGameInst) and add a dot to access it functions
FGame NewGameInst; // create an instance of or instantiate // made game but don't know it's data or things it holds
// Entry point for application run
int main() {
Game_Intro();
Game_loop();
system("PAUSE");
return 0;
}
// create function to ask questions declare it outside main
// Either create above call or reference above main to keep main at top
void Game_Intro() {
// introduce the game
constexpr int32 WORD_LENGTH = 6;
std::cout<< "Welcome to guess the ISO word" << std::endl;
std::cout<< "can you guess the " << WORD_LENGTH << " letter ISO word I'm thinking of" << std::endl;
/* // get a guess from the user
FText Guess = "";
std::cout<< "Enter your guess" << std::endl;
std::getline(std::cin, Guess);
std::cout<< "Your guess was " << Guess << std::endl; */
return;
}
FText Game_Guess() {
int32 CurrentGuesses = NewGameInst.GetCurrentTries(); // gets the current try
//std::cout << CurrentGuesses << std::endl; // print the current try
// get a guess from the user
FText Guess = "";
std::cout << "Attempt number : " << CurrentGuesses << std::endl;
std::cout << "Make a guess" << std::endl;
std::getline(std::cin, Guess);
return Guess;
}
void Game_loop() {
// make game instance
//FGame NewGameInst; // create an instance of or instantiate // made game but don't know it's data or things it holds
int32 TRIES = NewGameInst.GetMaxTries(); // replaces need for the constant TRIES vvvv
// constexpr int32 TRIES = 5; // number of tries variable
std::cout << TRIES << std::endl;
// loops for number of avaiable guesses
// TODO change it from for to while loop
for (int32 Guesses = 1; Guesses <= TRIES; Guesses++) {
FText Guess = Game_Guess();
// TODO Submit valid guess to game
BullCowCount BullsCows = NewGameInst.SubmitGuess(Guess);// submit guess and place in to instance of struct BullCowCount
// TODO Print number of bulls and cows
std::cout << "Bulls : " << BullsCows.Bulls;
std::cout << " Cows : " << BullsCows.Cows << std::endl;
std::cout << std::endl;
//std::cout<< "Your guess was : " << Guess << std::endl; // TODO make loop for checking valid answer
//std::cout<< std::endl;
if (Guesses == TRIES) {
std::cout<< "Nice try sorry you're out of guesses" << std::endl;
FText Answer = " ";
std::cout<< "would you like another go? : Y/N " << std::endl;
std::getline(std::cin, Answer);
if (Answer == "Y" || Answer == "y") {
NewGameInst.Reset();
Game_loop();
}
else {
std::cout<< "Thanks for playing" << std::endl;
}
}
}
return;
}
I can spot one issue. May not be your only issue. But here's a fix to start with.
Your Reset method defines a local variable of MyHiddenWord which gets discarded when Reset returns. The actual member variable of the FGame class, MyHiddenWord, never gets initialized.
void FGame::Reset()
{
MyCurrentTries = 1;
MaxTries = 7;
const FString MyHiddenWord = "cat"; // this is just a local variable
return;
}
I suspect you meant this:
void FGame::Reset()
{
MyCurrentTries = 1;
MaxTries = 7;
MyHiddenWord = "cat"; // actually initializes the member variable of FGame
return;
}
I'm working on an assignment that involves creating a linked list of applicants (stored as a class), each having a value for ID, grade, years, and a numerical value (score). I need to write a function that searches this list for the applicant with the highest score and returns it. I was able to locate the highest score, but I would only return that value, and not the entire class of that specific applicant. After changing my code, I now get outputs for each of the 4 values (ID, grade, years, and score) but they all show 0, which is the initialized value. Here is all the relevant code.
#include <iostream>
#include <fstream>
#include <iomanip>
#include "applicant.cpp"
using namespace std;
struct Linkapp
{
Applicant person;
Linkapp *next;
};
class Linkthem
{
protected:
Linkapp *start;
public:
Linkthem(void);
void link(Applicant);
void printthem(void);
Applicant returnbest(void);
};
Applicant best;
Linkthem::Linkthem()
{
start = NULL;
};
void
Linkthem::link(Applicant one)
{
Linkapp *p;
p = new Linkapp;
p->person = one;
p->next = start;
start = p;
}
Applicant Linkthem::returnbest (void)
{
Linkapp *travel;
travel = start;
best = travel->person;
while (travel != NULL)
{
if (travel->person.return_value() > best.return_value())
best = travel->person;
travel = travel->next;
}
return best;
}
int
main()
{
ifstream infile;
Applicant fellow;
Linkthem mylist;
int id, yrs;
char knowledge;
cout.setf(ios::fixed);
cout.precision(2);
infile.open("applicnt.dat");
while ( !infile.eof() )
{
infile >> id >> knowledge >> yrs;
fellow.store_id(id);
fellow.store_skill(knowledge);
fellow.store_years(yrs);
mylist.link(fellow);
}
mylist.printthem();
cout << best.return_id() << ' ' << best.return_skill() << ' ';
cout << best.return_years() << ' ' << best.return_value() << endl;
fellow = mylist.returnbest();
return 0;
}
And from the "applicant.cpp"
class Applicant
{
protected:
int id;
char skill;
int years;
float value;
void calc_value(void); // <--- NOT for general use, called by return_value
public:
Applicant(void);
void store_id(int);
void store_skill(char);
void store_years(int);
int return_id(void);
char return_skill(void);
int return_years(void);
float return_value(void);
};
The problem definitely lies within my returnbest function, I'm just not sure where.
Just used std::max_element and std::list (which is doubly linked) or std::forward_list (which is singly linked), but I would probably default to std::vector instead:
std::max_element(begin(list), end(list), [](Applicant const& a, Applicant const& b) {
return (a.return_value() < b.return_value());
});
If the comparison function is intended for the entire Applicant class, it might make sense to define an operator< for said class.
As you seem to have to write your own list, some hints:
Linkapp appears to be an internal detail of your class Linkthem, so no bad idea to make it a private inner class.
returnbest (and probably printthem, if I may assume analogous implementation) will fail with segmentation fault, if your list is empty. You need to check, if start is null first:
if(start)
{
// rest of your code
}
else
{
// return some appropriate default
// throw exception
// or whatever else seems appropriate to you
}
You have quite uncommon names for your getters/setters. There are two main variants for naming:
int getId(); // or get_id(), but cammel casing is more common these days
void setId(int id);
// vs
int id();
void id(int id);
There is no need for Applicant best to be a global variable. Rather place it within the functions as local variables.
Now your actual problem:
Keep a close look on your main function - where do you call returnbest first? After you wrote out the values of best. This means that you never assigned any other value to best than the default. You have to place fellow = mylist.returnbest(); before the lines where you output best. But then use fellow for output instead of best, and you are free to make best a local variable within returnbest function...
mylist.printthem();
cout << best.return_id() << ' ' << best.return_skill() << ' ';
cout << best.return_years() << ' ' << best.return_value() << endl;
fellow = mylist.returnbest();
I don't know what you do in the printthem() member function, as you did not provide implementation of this function, but I assume you don't set variable best.So, you are printing an unset variable, which likely is initialized to zero.
What you want to do is more likely:
mylist.printthem();
best = mylist.returnbest();
cout << best.return_id() << ' ' << best.return_skill() << ' ';
cout << best.return_years() << ' ' << best.return_value() << endl;
Class C {
struct Something {
string s;
// Junk.
}
// map from some string to something.
map<string, Something> map;
// Some more code:
const Something *Lookup(string k) const {
const something *l = SomeLookUpFunction();
cout << l;
cout << &l->s;
cout << l->s;
return l;
}
}
// Some Test file
const C::Something *cs = C::Lookup("some_key");
cout << cs;
cout << &cs->s;
cout << cs->s;
The weird thing is this outputs:
* For lookup fucntion:
0x9999999
0x1277777
some_string
* For test code
0x9999999
0x1277777
000000000000000000000000000000000000000000 ....
In test file it gives a very long string of zeros, but the addresses are the same. Any idea what could be going wrong ?
Since you have not shared code for function SomeLookUpFunction, I have to guess that you are returning pointer to local object of type Something. This is a bad idea, see similar QA.
To start fixing your code, you should start by returning simple object, instead of pointer, as shown below:
// Some more code:
const Something lookup(string k) const {
const something l = SomeLookUpFunction(); // return simple object
cout << &l;
cout << &l.s;
cout << l.s;
return l; // same object
}
Of course you should improve the code by providing copy constructors for type something and even improving your map.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I would like to start this thread by thanking you for taking to the time to read my query.
I have created a function called retreiveFile which as you would expects retreives a file and reads from it. The text it reads is a set of numbers and text which represent names, cost and that sort of thing.
I have used istringstream to read through the file, determine the starting number(so I know what the line represents(property, card, ect)). Currently I have the file outputting the text but only with its corresponding data.
Example:
9 Oakmoor Road 80 5 0
9 Eldon Road 50 5 0
I need to know how I could pass this information into a class as I assume because I am going to have many objects of the same class I need to pass the data into main somehow.
(I tried creating the class using constructor within the function but it would not work)
I am assuming I would have to create pointers for the information, pass it to main, create the constructors and then delete the pointers.
My question to you would be how could I do this efficiently as I need to create around 30 objects which could fit in several different types of classes as some have different parameters.
I'm sorry in advance in some information seems vague or confusing I am still, in my head, trying to picture how I could do it.
An example of one of the ways I've separated the text within the file so I can easily pass it over to its correct class.
if (word[i].find("1") == 0){ //starts with 1
istringstream is(word[i]);
string aword;
int loopTimes = 0;
while (is >> aword) { // read each word from line
string propertyArray[6];
if (loopTimes == 0){
string stringIdentificationNum = aword;
/* const char * charIdentificationNum = stringIdentificationNum.c_str();
int identificationNum = atoi(charIdentificationNum); */
cout << "(1.1)" << aword;
propertyArray[0] = aword;
}
else if (loopTimes == 1){
cout << "(1.2)" << aword;
propertyArray[1] = aword;
}
else if (loopTimes == 2){
cout << "(1.3)" << aword;
propertyArray[2] = aword;
}
else if (loopTimes == 3){
cout << "(1.4)" << aword;
propertyArray[3] = aword;
}
else if (loopTimes == 4){
cout << "(1.5)" << aword;
propertyArray[4] = aword;
}
else if (loopTimes == 5){
cout << "(1.6)" << aword << endl;
propertyArray[5] = aword;
}
loopTimes++;
/* Property(propertyArray[0], propertyArray[1], propertyArray[2], propertyArray[3], propertyArray[4], propertyArray[5]); */
}
}
An example of the propertyClass
class Property : public Card{
private:
int identificationNum;
string propertyName;
int propertyCost;
int propertyRent;
int propertyColour;
public:
//constructor
Property::Property(int inputIdentificationNum, string inputFName, string inputSName, int inputCost, int inputPropertyRent, int inputPropertyColour){
setIdentificationNum(inputIdentificationNum);
setFirstName(inputFName, inputSName);
setPropertyCost(inputCost);
setPropertyRent(inputPropertyRent);
setPropertyColour(inputPropertyColour);
cout << "Property Created" << endl;
}
//set data
void setIdentificationNum(int inputIdentificationNum){
identificationNum = inputIdentificationNum;
}
void setFirstName(string inputFName, string inputSName){
string nameCombined = inputFName + " " + inputSName;
propertyName = nameCombined;
}
void setPropertyCost(int inputCost){
propertyCost = inputCost;
}
void setPropertyRent(int inputPropertyRent){
propertyRent = inputPropertyRent;
}
void setPropertyColour(int inputPropertyColour){
propertyColour = inputPropertyColour;
}
//retreive data
int getIdentificationNum() {
return identificationNum;
}
string getName(){
return propertyName;
}
int getPropertyCost(){
return propertyCost;
}
int getPropertyRent(){
return propertyRent;
}
int getPropertyColour(){
return propertyColour;
}
};
Thank you in advance for reading this thread.
Passing pointers around is unnecessary for this task and is actually frowned on. An objects data should stay locked up and hidden in the object unless you have a really good reason to expose it. In this case OP doesn't.
What follows cleans up OP's code and fixes some of the problems that made their attempt unworkable and probably lead them down the road to over-complicating things further.
Example is a container for a list of properties. Rather than passing around pointers to to the properties, OP can pass around references to Example and read the properties from example. This allows Example to defend itself from its clients. With a pointer to a property, a client could mistakenly change change a value that could result in breaking Example or another client of Example. With a Getter method, Example can control access to the properties with whatever grain is required.
Example, in this case, allows everyone to see properties, so long as the property exists, but does not allow changing the property.
#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>
class Example
{
private:
static constexpr size_t MAX_PROPERTIES = 6;
std::string propertyArray[MAX_PROPERTIES];
propertyArray is now a member variable and has scope that matches the object. Consider using a vector. It is not arbitrarily limited in size
public:
Example(std::stringstream & is)
{
std::string aword;
size_t looptimes = 0;
while (is >> aword && looptimes < MAX_PROPERTIES)
{
std::cout << "(1." << looptimes + 1 << ")" << aword << std::endl;
propertyArray[looptimes] = aword;
looptimes++;
This is where making propertyArray a vector really helps. You can use the push_back method to keep adding more and more properties. If you have a case with 8 properties in the future, it uses the exact same code as the 8 property version and you don't have to guard against overflow with the && looptimes < 6 in the while
}
}
std::string getProperty(size_t propertyNo)
New method used to get the properties for clients of Example. That way you don't have to pass around pointers to Example's data. Just pass around Example and if Example wants to give data, it can. No one can use an unprotected back door into Example to screw with Example's data without permission.
{
if (propertyNo < MAX_PROPERTIES)
{
return propertyArray[propertyNo];
}
throw std::out_of_range("Invalid property number");
}
};
And to test it out...
int main()
{
std::stringstream is ("A B C D E F G");
Example test(is);
try
{
std::cout << test.getProperty(4) << std::endl;
std::cout << test.getProperty(6) << std::endl;
}
catch (std::out_of_range & exc)
{
std::cout << exc.what() << std::endl;
}
}
Output:
(1.1)A
(1.2)B
(1.3)C
(1.4)D
(1.5)E
(1.6)F
E
Invalid property number
And now with a std::vector:
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
class Example
{
private:
std::vector<std::string> propertyArray;
public:
Example(std::stringstream & is)
{
std::string aword;
while (is >> aword)
{
propertyArray.push_back(aword);
std::cout << "(1." << propertyArray.size() << ")" << aword << std::endl;
}
}
std::string getProperty(size_t propertyNo)
{
if (propertyNo < propertyArray.size())
{
return propertyArray[propertyNo];
}
throw std::out_of_range("Invalid property number");
}
};
int main()
{
std::stringstream is ("A B C D E F G");
Example test(is);
try
{
std::cout << test.getProperty(4) << std::endl;
std::cout << test.getProperty(7) << std::endl;
}
catch (std::out_of_range & exc)
{
std::cout << exc.what() << std::endl;
}
}
Output:
(1.1)A
(1.2)B
(1.3)C
(1.4)D
(1.5)E
(1.6)F
(1.7)G
E
Invalid property number
I am making an hierarchy of sorts and am having trouble adding an element to a vector. I simplified the code and still cannot add an element to the vector as expected. The hierarchy looks like:
Pdb > Chain > strings
Pdb and Chain are class names and strings is the name of a vector belonging to Chain. I cannot push_back to add a string to strings. You may get a better idea looking at my code:
Chain Class:
class Chain {
string chain_id;
vector<string> strings;
public:
Chain(string id_) { chain_id = id_; }
vector<string> GetStrings() { return strings; }
void AddString(string s) {
cout << "Size of strings BEFORE push_back in AddString: " << strings.size() << endl;
strings.push_back(s);
cout << "Size of strings AFTER push_back in AddString: " << strings.size() << endl;
}
string GetChainId() { return chain_id; }
};
Pdb class:
class Pdb {
string pdb_id;
vector<Chain> chains;
public:
Pdb(string id_) { pdb_id = id_; }
vector<Chain> GetChains() { return chains; }
void AddChain(Chain c) { chains.push_back(c); }
string GetPdbId() { return pdb_id; }
};
main:
int main () {
vector<Pdb> pdbs;
pdbs.push_back(Pdb("1ubq"));
cout << "\n\t1. " << pdbs[0].GetPdbId() << endl;
pdbs[0].AddChain(Chain("A"));
cout << "\n\t2. " << pdbs[0].GetChains()[0].GetChainId() << endl;
pdbs[0].GetChains()[0].AddString("Whateva");
cout << "\n\t3. Size of strings after AddString in main: " << pdbs[0].GetChains()[0].GetStrings().size() << endl;
return 0;
}
This outputs:
1. 1ubq
2. A
Size of strings BEFORE push_back in AddString: 0
Size of strings AFTER push_back in AddString: 1
3. Size of strings after AddString in main: 0
As you can see the AddString function is adding an element to stings within the AddString function itself but when I GetStrings back in main, after executing AddString, strings is empty. I do not understand why this is happening. Any help would be much appreciated.
The problem is that you return a copy of the member, not the member itself:
vector<Chain> GetChains()
should be
vector<Chain>& GetChains()
for this to work.
I must note that you're heavily breaking the single responsibility principle. You're operating on members directly, which can't be a good idea. Consider replacing:
pdbs[0].GetChains()[0].AddString("Whateva");
with something like
pdbs[0].AddStringToChain(0,"Whateva");