Having 2 different objects (or instances (I do not know if they have any differences)) of a class, will they instantiate the constructor individually?
For example; Having a constructor that makes a variable z equal to 0. A function of the class adds 10 to z. So when I use the other object to call the same function, z will be 20 (previous value plus 10) or will it be 10 (0+10)?
Many thanks!
If you have a class A and a class B
struct A {
int x = 0;
void inc() { x+=10; }
};
struct B {
static int x;
void inc() { x+=10; }
};
int B::x = 0;
int main() {
A a1;
a1.inc();
std::cout << a1.x << '\n';
A a2;
a2.inc();
std::cout << a2.x << '\n';
B b1;
b1.inc();
std::cout << b1.x << '\n';
B b2;
b2.inc();
std::cout << b2.x << '\n';
}
Output:
10
10
10
20
For instances of class A the member variable x is not shared. Therefore a1.x and a2.x are both 10 after the respective incrementation.
However, for class B the keyword static declares x as a class variable that is shared among all instances. So incrementation in what-so-ever instance always increments the class member. After the first incrementation via b1.inc()the value of B::x is 10 and after the second incrementation via b2.inc() the value is 20.
Related
When the friendly function add is used to print the value of sum variable of two classes, the correct output is printing. But, when then display function of their respective class are used, garbage value is printing.
What's wrong with the code?
#include <iostream>
using namespace std;
class DB;
class DM {
int m, cm;
float sum;
public:
void read()
{
cout << "Enter meters and centimeters respectively\n";
cin >> m >> cm;
}
void display(void)
{
cout << sum << " meters\n";
}
friend void add(DM p1, DB p2);
};
class DB {
int feet, inch;
float sum;
public:
void read()
{
cout << "Enter feets and inches respectively\n";
cin >> feet >> inch;
}
void display(void)
{
cout << sum << " feets\n";
}
friend void add(DM p1, DB p2);
};
void add(DM p1, DB p2)
{
float a = p2.feet * 12;
float b = a + p2.inch;
float c = b * .3048 + p1.m + p1.cm * .01;
//cout << c << endl;
p1.sum = c;
//cout << p1.sum << endl;
//p2.sum = (c/12)/.3048;
cout << p2.sum << endl;
}
int main()
{
DM obj1;
DB obj2;
obj1.read();
obj2.read();
add(obj1, obj2);
obj1.display();
obj2.display();
}
The problem is that you print sum but you never initialize the sum of obj1 and obj2.
You initialize sum only inside add() but you pass values to add() by copy, so you initialize sum only in temporary objects.
When you print obj1.sum and obj2.sum (through display()), the sum member are still not-initialized.
So the garbage.
Try passing objects by reference
// ..........V........V
void add (DM & p1, DB & p2)
This way the initialization of sum inside add() has effect also for calling objects.
Problem description
I am trying to understand how the shared_ptr counters work. In my class A when I used a getter the counter incremented by 1. When used an instance of A in class B the counter incremented by 2. When I got Done with class B the destructor of A got called twice.
What I didn't understand and what confused me is the following:
Why did the counter of A increment by 1 when we called the getter a.a(). Is it because we returned a pointer by Copy so now we have 2 pointers right?
Why do we have a counter of 3 when the desctructor of A was called?
In class B why did the counter increment by 2?
After finishing of class B how was the destructor of A called?
When I use reset in the both destructors it gets weirder.
Source Code
#include <iostream>
#include <memory>
using namespace std;
class A {
public:
A(int a):_a( make_shared<int>(a)) {cout <<"A constructor" << endl;}
~A(){/*_a.reset();*/cout <<"After destructor, number of As "<< _a.use_count() <<endl;}
std::shared_ptr<int> a(){return _a;}
//private:
std::shared_ptr<int> _a;
};
class B {
public:
B(A a):_b( make_shared<A>(a)) {cout <<"B constructor" << endl;}
~B(){ /*_b.reset();*/ cout <<"After destructor, number of Bs "<< _b.use_count() << endl;}
std::shared_ptr<A> b(){return _b;}
private:
std::shared_ptr<A> _b;
};
int main()
{
int number = 10;
A a(number);
cout <<"counter of A is " << a._a.use_count() << endl;
cout <<"counter of A is " << a.a().use_count() << endl;
B b(a);
cout <<"counter of A is " << a.a().use_count() << endl;
cout <<"counter of B is " << b.b().use_count() << endl;
return 0;
}
A--->Number: Counter = 1
B(constructor) pass A by value : counter = 2
B--->Number: Counter = 3
Output without reset
A constructor
counter of A is 1
counter of A is 2
B constructor
After destructor, number of As 3
counter of A is 3
counter of B is 2
After destructor, number of Bs 1
After destructor, number of As 2
After destructor, number of As 1
Output with reset
A constructor
counter of A is 1
counter of A is 2
B constructor
After destructor, number of As 0
counter of A is 3
counter of B is 2
After destructor, number of As 0
After destructor, number of Bs 0
After destructor, number of As 0
A quick answer
Everytime you call a.a() it returns a new shared pointer to the resources. The first one is the member variable. They are eventually released but there's no quarantees as you don't store the returned shared pointer into a variable (which would bind it to a scope).
The first After destructor, ... is because you copy value of A a into constructor of B. If you wish to avoid copy, then use a reference B(A& a).
The number 3 is because of three shared_pointers, the A a internal one, the returned but not released a.a() result AND the copy of A a passed to the constructor of B.
In class B you also return new shared pointer in b.b() -> increment counter by one.
I hope this covers all of your questions, I can try to clarify further if you have any questions.
#include < iostream >
#include < iomanip >
using namespace::std;
#include < string.h >
class Human {
char Name[20];
int Age;
float Weight;
public:
Human() {
strcpy(Name, " ");
Age = Weight = 0;
}
Human(int AGE) {
this - > Age = Age;
}
Human(float Weight) {
this - > Weight = Weight;
}
Human(char * s) {
strcpy(this - > Name, s);
}
void GetData() {
cout << endl << "Enter the name : ";
gets(Name);
cout << endl << "Enter the Age : ";
cin >> Age;
cout << endl << "Enter the Weight :";
cin >> Weight;
}
void Display() {
cout << endl << "Name :" << Name;
cout << endl << "Age :" << Age;
cout << endl << fixed << "Weight :" << Weight << " Kg";
}
};
int main() {
Human h1;
h1 = 23; //It will assign 23 in Age
h1 = 67.45 f; //It will assign 67.45 in Weight
h1 = "Jimmy Neutron";
h1.Display();
cin.get();
return 0;
}
There are several issues here but let me start with the one you asked.
Why is the output like this:
Name :Jimmy Neutron Age :4194304 Weight :0.000000 Kg – Udesh
The reason is every time you assign values like this to your object i.e., h1
h1 = 23; //It will assign 23 in Age
h1 = 67.45f; //It will assign 67.45 in Weight
h1 = "Jimmy Neutron";
This is what is happening behind the scene, move assignment operator gets called.
h1.operator=(Human(23));
h1.operator=(Human(67.4499969f));
h1.operator=(Human("Jimmy Neutron"));
So, the other two arguments get overwritten everytime you write one of this.
To understand the problem, try using your display function after every assignment statement and see the output.
Now lets come to other issues.
Please avoid using char array and char pointer. We have the wonderful std::string for the very same purpose, please use it. IIRC, every major compiler warns about string literal to char * conversion.
I do not know if you realized, but the parameter name in one of your constructor that takes int is AGE but you are assigning age.
Please avoid using deprecated functions - [hint: gets]
I am still new to c++, so bear with me.
I was trying to learn more about how std::move works and I saw an example where they used std::move to move the string to a different function and then showed using std::cout that no string remained. I thought cool, let's see if I can make my own class and do the same:
#include <iostream>
#include <string>
class integer
{
private:
int *m_i;
public:
integer(int i=0) : m_i(new int{i})
{
std::cout << "Calling Constructor\n";
}
~integer()
{
if(m_i != nullptr) {
std::cout << "Deleting integer\n";
delete m_i;
m_i = nullptr;
}
}
integer(integer&& i) : m_i(nullptr) // move constructor
{
std::cout << "Move Constructor\n";
m_i = i.m_i;
i.m_i = nullptr;
}
integer(const integer& i) : m_i(new int) { // copy constructor
std::cout << "Copy Constructor\n";
*m_i = *(i.m_i);
}
//*
integer& operator=(integer&& i) { // move assignment
std::cout << "Move Assignment\n";
if(&i != this) {
delete m_i;
m_i = i.m_i;
i.m_i = nullptr;
}
return *this;
}
integer& operator=(const integer &i) { // copy assignment
std::cout << "Copy Assignment\n";
if(&i != this) {
m_i = new int;
*m_i = *(i.m_i);
}
return *this;
}
int& operator*() const { return *m_i; }
int* operator->() const { return m_i; }
bool empty() const noexcept {
if(m_i == nullptr) return true;
return false;
}
friend std::ostream& operator<<(std::ostream &out, const integer i) {
if(i.empty()) {
std::cout << "During overload, i is empty\n";
return out;
}
out << *(i.m_i);
return out;
}
};
void g(integer i) { std::cout << "G-wiz - "; std::cout << "The g value is " << i << '\n'; }
void g(std::string s) { std::cout << "The g value is " << s << '\n'; }
int main()
{
std::string s("Hello");
std::cout << "Now for string\n";
g(std::move(s));
if(s.empty()) std::cout << "s is empty\n";
g(s);
std::cout << "\nNow for integer\n";
integer i = 77;
if(!i.empty()) std::cout << "i is " << i << '\n';
else std::cout << "i is empty\n";
g(i);
std::cout << "Move it\n";
g(std::move(i)); // rvalue ref called
if(!i.empty()) std::cout << "i is " << i << '\n';
else std::cout << "i is empty\n";
g(i);
return 0;
}
And this is my output:
Now for string
The g value is Hello
s is empty
The g value is
Now for integer
Calling Constructor
Copy Constructor
i is 77
Deleting integer
Copy Constructor
G-wiz - Copy Constructor
The g value is 77
Deleting integer
Deleting integer
Move it
Move Constructor
G-wiz - Copy Constructor
The g value is 77
Deleting integer
Deleting integer
i is empty
Copy Constructor
Process returned 255 (0xFF) execution time : 7.633 s
Press any key to continue.
As you can see, it crashes when it enters g the second time, never even getting to the operator<<() function. How is it that the empty std::string s can be passed to g where my empty integer i crashes the program?
Edit: Fixed new int vs. new int[] error. Thanks n.m.
Your "empty integer" crashes the program because it contains a null pointer. You are trying to dereference it when you use it at the right hand side of the assignment.
An empty string is a normal usable string. There are no unchecked null pointer dereferences in the std::string code.
You have to ensure that the empty state of your object is a usable one. Start with defining a default constructor. Does it make sense for your class? If not, then move semantic probably doesn't either. If yes, a moved-from object in the move constructor should probably end up in the same state as a default-constructed object. A move assignment can act as a swap operation, so there the right-hand-side may end up either empty or not.
If you don't want to define a usable empty state for your class, and still want move semantics, you simply cannot use an object after it has been moved from. You still need to make sure that an empty object is destructible.
In c++ I can add a reference to a value type, for example :
int a = 12;
int &b = a;
a--;
cout << "a = " << a << ", b = " << b << endl;
Will give :
a = 11, b = 11
Is there a way to do the same in vala without using pointers ?
Is there a way to do the same in vala
Yes.
without using pointers ?
No.
If, however, you are passing them to a function, you can use a ref parameter:
void decrement (ref value) {
value--;
}
void do_stuff () {
int a = 12;
decrement (ref a);
assert (a == 11);
}