How to delay Destructor call in a loop - c++

// Online C++ compiler to run C++ program online
#include <iostream>
#include <iterator>
#include <set>
int index;
int member[5] = {0,1,2,3,4};
class Animal{
public:
Animal(int val){
member[val]=-1;
}
~Animal(){
member[index]=index;
}
};
int main() {
// Write C++ code here
for(int i=0;i<5;i++){
std::cout<<member[i]<<" ";
}
std::cout<<std::endl;
for(int i=0;i<5;i++){
index=i;
Animal a(i);
}
for(int i=0;i<5;i++){
std::cout<<member[i]<<" ";
}
return 0;
}
In following code the output is:
0 1 2 3 4
0 1 2 3 4
But I am interested in the following output:
0 1 2 3 4
-1 -1 -1 -1 -1
So every time we perform Animal a(i); its constructor gets called and member[val]=-1 but immediately after its iteration the destructor gets called which makes the value back to val. member[index]=index.
How can we delay the call to destructor in this case?
I want the member[5]={-1,-1,-1,-,1,-1} after the for loop ends
and member[5]={0,1,2,3,4} restored to original value only when main() exists.

While it's an ugly hack, how about using a vector that gets destructed after the code you're interested in?
Perhaps something like:
{
std::vector<Animal> animals;
for(int i = 0; i < 5; ++i){
std::cout << member[i] << ' ';
}
std::cout << '\n';
for(int i = 0; i < 5; ++i){
animals.emplace_back(i);
}
for(int i = 0; i < 5; ++i){
std::cout << member[i] << ' ';
}
std::cout << '\n';
// Here the vector object life-time ends
// All Animal object will be destructed
}
As noted, this solution will use the last value of index when the Animal object are being destructed, and since it's never used by the above code it will stay at its (implicitly) initialized value of 0.
You need to store the "index" passed to the constructor in an actual member variable, and use it in the destructor:
class Animal
{
public:
Animal(int index)
: my_index{ index }
{
}
~Animal()
{
member[my_index] = my_index;
}
private:
int my_index;
};
After this you can remove the global index variable, as it's no longer used or needed.

Related

C++: confusion about accessing class data members while multithreading

I have the following minimal working example in which I create a number of markov_chain objects in a vector chains and an equal number of thread objects in a vector workers, each of which executes a markov_chain class member function sample on each of the corresponding markov_chain objects. This function takes some integer (99 in the below example) and assigns it to the acceptance public data member of the markov_chain object. I then print the value of acceptance for each object in the vector.
#include <iostream>
#include <thread>
#include <algorithm>
#include <vector>
class markov_chain
{
public:
unsigned int length{0}, acceptance{0};
markov_chain(unsigned int l) {length=l;}
~markov_chain() {}
void sample(int acc);
};
void markov_chain::sample(int acc)
{
acceptance = acc;
std::cout << length << ' ' << acceptance << std::endl;
}
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
for (int i = 0; i <= number_of_threads; i++) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, chains[i], 99));
}
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
for (int i = 0; i <= number_of_threads; i++) {
std::cout << chains[i].length << ' ' << chains[i].acceptance << std::endl;
}
return 0;
}
Upon executing, the program outputs
1000 99
1000 99
1000 99
1000 99
1000 0
1000 0
1000 0
1000 0
So the program failed to change the value of acceptance for the objects in the vector chains. I don't know why this happens; the function sample successfully assigns the desired value when I use it without creating threads.
There are 2 problems with your code:
when creating each std::thread, you are passing a copy of each object as the this parameter of sample().
Pushing multiple objects into the chains vector the way you are doing may cause the vector to re-allocate its internal array, thus invaliding any object pointers you have already passed to existing threads, since those original objects are now gone after the re-allocation.
You need to fully initialize the chains vector before creating any of the threads. And you need to pass a pointer to each object to each thread.
You can reserve() the array up front to avoid re-allocation while pushing into it, eg:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.reserve(number_of_threads);
for (int i = 0; i < number_of_threads; ++i) {
chains.push_back(markov_chain(number_of_samples));
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo
However, since all of the objects are being initialized with the same starting value, an easier way is to simply get rid of chains.push_back() altogether and use chains.resize() instead, eg:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains;
std::vector<std::thread> workers;
chains.resize(number_of_threads, markov_chain(number_of_samples));
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo
Or, even use the vector constructor itself:
int main()
{
int number_of_threads{3};
int number_of_samples{1000};
std::vector<markov_chain> chains(number_of_threads, markov_chain(number_of_samples));
std::vector<std::thread> workers;
for (int i = 0; i < number_of_threads; ++i) {
workers.push_back(std::thread(&markov_chain::sample, &chains[i], 99));
}
for(auto &t : workers) {
t.join();
}
for (auto &c : chains) {
std::cout << c.length << ' ' << c.acceptance << std::endl;
}
return 0;
}
Demo

Having a problem with getting the right value with private variable

This is a program that takes an array and print the sum of the odd (named m_sumOdd) and even (named m_sumEven) numbers of that array using class. However when i run it and enter some values like (4, 6, 9, 3, 1) the m_sumEven returns 10 and m_sumOdd returns 2037769787. What's the problem with m_sumOdd ?
#include <iostream>
#include <string>
class myClass {
private:
int m_sumEven;
int m_sumOdd;
public:
myClass() {
m_sumEven = 0;
m_sumOdd = 0;
}
myClass(int arr[]) {
for (int i = 0; i < 5; i++)
{
if (arr[i] % 2 == 0) {
m_sumEven += arr[i];
}
else if (arr[i] % 2 != 0) {
m_sumOdd += arr[i];
}
}
print();
}
void print() {
std::cout << m_sumEven << "\t" << m_sumOdd << std::endl;
}
};
int main(){
int main_arr[5];
for (int j = 0; j < 5; j++)
{
std::cin >> main_arr[j];
}
myClass obj(main_arr);
std::cin.get();
}
From your comment:
the problem is from my uni textbook and it specify that the private variables shall be initialized in the default constructor and the other constructor find the sum
I'm not sure what solution the textbook is looking for, but there is a mechanism that allows one constructor to use another.
class myClass {
private:
int m_sumEven;
int m_sumOdd;
public:
myClass() {
m_sumEven = 0;
m_sumOdd = 0;
}
myClass(int arr[]): myClass() { // <-------
....
This is called delegating constructors. This makes your myClass(int arr[]) constructor use the myClass() constructor before continuing on.
When you do not initialize your variable in C++, the default value of that variable is whatever garbage value happens to already be in that memory location. So if you initialize your privates variables as zeros (as in your non-parameterized constructor), your problem will be solved.
The second constructor doesn't initialize the private variables like the first one.
m_sumEven = 0;
m_sumOdd = 0;
Put these to the second constructor as well.
Even better, put them at the declaration:
int m_sumEven = 0;
int m_sumOdd = 0;
And now you don't need the first constructor.
Unrelated: consider using std::initializer_list instead. This provides you a safe way to know how many items are passed to the constructor, while now you have a fixed 5 in mind which may change later.

Garbage values are printed when I try to print the elements of an array using pointer

I have a class named mvector which has two private variables, num (denotes number of elements in the array), and an integer pointer to store the array address.
mvector has 2 public functions, get() and print() to get the elements of the array, and print them (respectively).
However, when I try to print the values, some values are correct, while others are garbage values.
#include<iostream>
using namespace std;
class mvector
{
private:
int num;
int *ele;
public:
void get();
void print();
};
void mvector::get()
{
cin>>num;
int data[num];
for(int i=0; i<num; i++)
{
cin>>data[i];
}
ele=data;
}
void mvector::print()
{
for(int i=0; i<num; i++)
{
cout<<*ele<<endl;
ele++;
}
}
int main()
{
mvector v1;
v1.get();
v1.print();
}
Input: 5 1 2 3 4 5
Expected Output: 1 2 3 4 5
Actual Output: 1 1 1877615960 4 5
The program does not make a great sense.
For example the variable length arrays is not standard C++ feature. So the declaration of the array
cin>>num;
int data[num];
is not correct.
Within the function get the data member ele is assigned with the address of the first element of a local array that will not be alive after exiting the member function. So using this pointer in the member function print invokes undefined behavior.
You have to define the array dynamically.
Moreover within the function print the pointer ele is incremented and loses its initial value. It means that you could call the function the second time
You should define a class with constructors and destructor.
More or less working code can look the following way.
#include <iostream>
class mvector
{
private:
size_t num = 0;
int *ele = nullptr;
public:
void get();
void print() const;
};
void mvector::get()
{
size_t n;
std::cin >> n;
if ( n != num )
{
delete [] ele;
ele = nullptr;
if ( n != 0 )
{
ele = new int[n];
}
num = n;
}
if ( num != 0 )
{
for ( size_t i = 0; i < num; i++)
{
std::cin >> ele[i];
}
}
}
void mvector::print() const
{
int *p = ele;
for ( size_t i = 0; i < num; i++ )
{
std::cout << *p << ' ';
++p;
}
std::cout << '\n';
}
int main()
{
mvector v1;
v1.get();
v1.print();
v1.get();
}
For the input like this
5
1 2 3 4 5
0
The output will be
1 2 3 4 5
and the allocated memory will be freed.
The line
ele=data;
is the source of your problems.
data is a local array, a non-standard VLA, but it is still a local array. When the function returns data is destructed and ele points to an object that is no longer valid. Accessing ele after the function returns is cause for undefined behavior. The garbage values you are seeing is just one symptom of undefined behavior.
You can change that function to use:
void mvector::get()
{
cin>>num;
ele = new int[num];
for(int i=0; i<num; i++)
{
cin>>ele[i];
}
}
That will solve your immediate problem. However, there are other issues you have to contend with when managing memory yourself. See http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three for additional details.

Operator Overloading and array handling in C++

I am writing a Little Man computer simulation and i want to overload the Indexing operator []. I have create a class called LMC and have done the following:
#include <iostream>
using namespace std;
class LMC
{
public:
LMC();
void display();
int& operator[](int index);
~LMC();
private:
int **array;
};
LMC::LMC()
{
array = new int*[100];
for(int i = 0; i < 100; i++)
{
array[i] = new int[3];
}
return array;
}
void LMC::display()
{
for(int i = 0; i < 100;i++)
{
for(int j = 0; j <3;j++)
{
array[i][j] = 0;
array[i][2] = i;
cout << array[i][j]<<" ";
}
cout << endl;
}
}
int& LMC::operator[](int index)
{
return array[index][2];
}
LMC::~LMC()
{
for(int i =0; i < 100 ; i++)
{
delete [] array[i];
}
delete [] array;
array = NULL;
}
int main()
{
LMC littleman;
while(true)
{
int mailbox;
int function;
cout << "What is Mailbox number?" << endl;
cin >> Mailbox;
cout << "What is the function you want to use?" <<endl;
cin >> finction;
//the function is numbers eg 444 and 698;
littleman.display();
littleman[Mailbox] = function;
}
return 0;
}
I can run the program with no error. When i state that mailbox = 0 and function = 123 the is no problem.
This is displayed:
0 0 0
1 0 0
2 0 0
3 0 0
//continuing to 99
This display is wrong. The following must be displayed:
0 0 123
1 0 0
2 0 0
//continuing to 99
Do i have a logical error or am i overriding the array to display the original and how can i fix it?
Your code has a number of errors which will not let it compile namely:
in the LMC() constructor, you have return array;. Constructors never return anything (they don't even have the return type), so you can not use return in them.
after void LMC::display(), you have a ;, which is an error, because this is not a definition, but implementation. You should omit it and just leave void LMC::display() { <...> }
void LMC::display() is missing the closing } in the end, right before the operator[].
in main() you have typos in Mailbox (capital M in one case, and normal m in another. In C+++ Mailbox and mailbox are different variables) and finction instead of function.
As for your problem, you are rewriting the values of the aray in display() function:
array[i][j] = 0;
array[i][2] = i;
That's why you don't see any results.
These lines
array[i][j] = 0;
array[i][2] = i;
in LMC::display() destroy the contents of the array you're trying to display.
Furthermore, there's an extra semicolon at the end of void LMC::display();, so your code is not supposed to compile.

Operator Overloading

I'm new to C++, this is my first week since the upgrade from fortran. Sorry if this is a simple question, but could someone help me with operator overloading. I have written a program which has two classes. One object contains a vector and two scalars, the other class simply contains the first object. In a test implementation of this code I suspect the operator overloading to be at fault. The program tries to accomplish the following goals:
1) Initialize first structure.
2) Initialize a second structure containing the initialized first structure. After this is imported, the value val0 = 10 is added to every element of the vector in the enclosing structure, structure2.structure1 .
3) Output structure1 and structure2 variables to compare.
For this simple program my output is:
100
100
0
0
0 0 10
1 1 11
2 2 12
3 3 13
...
I was expecting:
100
100
0
10
0 0 10
1 1 11
2 2 12
3 3 13
...
Clearly my overloaded = operator is copying my vector properly, but one of the scalars? Could someone help?
#include <iostream>
using namespace std;
typedef double* doublevec;
// This first class contains a vector, a scalar N representing the size of the vector, and another scalar used for intializing the vector.
typedef class Structure1
{
int N, vec0;
doublevec vec;
public:
// Constructor and copy constructor.
Structure1(int Nin, int vecin) : N(Nin), vec0(vecin) { vec = new double [N]; for(int i = 0; i < N; i++) { vec[i] = i + vec0; } }
Structure1(const Structure1& structurein);
// Accessor functions:
int get_vec0() { return vec0; }
int get_N() { return N; }
doublevec get_vec() { return vec; }
// Overide equivalence operator:
Structure1& operator=(const Structure1& right)
{
//Handle Self-Assignment
if (this == &right) return *this;
N = right.N;
vec0 = right.vec0;
for (int i = 0; i < N; i++)
{
vec[i] = right.vec[i];
}
return *this;
}
// Destructor:
~Structure1() { delete []vec; }
} Structure1;
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for(int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
}
// This class just contains the first structure.
typedef class Structure2
{
Structure1 structure;
// Mutator Function:
void mutate_structure();
public:
// Constructor:
Structure2(const Structure1& structurein) : structure(structurein) { mutate_structure(); }
// Accessor Function:
Structure1 get_structure() { return structure; }
// Destructor:
~Structure2() {}
} Structure2;
void Structure2::mutate_structure()
{
int N = structure.get_N();
Structure1 tempstruct(N,10);
structure = tempstruct;
}
int main (int argc, char * const argv[])
{
const int N = 100;
Structure1 structure1(N,0);
Structure2 structure2(structure1);
cout << structure1.get_N() << endl;
cout << structure2.get_structure().get_N() << endl;
cout << structure1.get_vec0() << endl;
cout << structure2.get_structure().get_vec0() << endl;
for(int i = 0; i < N; i++)
{
cout << i << " " << structure1.get_vec()[i] << " " << structure2.get_structure().get_vec()[i] << endl;
}
return 0;
}
it looks like vec0 isn't initialized by your copy constructor...
Try modifying your copy constructor to:
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for (int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
// ADD THIS LINE
vec0 = structurein.vec0;
}
Your copy-constructor Structure1::Structure1(const Structure1 &) doesn't copy vec0. It's not getting initialised at all, so gets whatever is in memory.
Also, you might want to check Structure1's operator=. If you assign a large vector to a small vector, then you'll potentially overflow the array in the destination. You might need to reallocate memory in operator=.