How does the default operator= works in C++? - c++

I've had some hard times trying to understand how the default copy constructor and the default operator= work in C++.
In the following program, I don't see why the last line c0 = b2; cout <<endl; prints out 32944 .
-Does the operator= call the copy constructor if defined ? if not how does it behave ? in this case it seems that b0 when assingned to c0 used the copy constructor:
C(const B& x) : B(x), a(1){z=0; cout <<"9";}
-How did the statement c0 = b2; use the operator= of the class A (the 44 at the end of the result)?
#include <iostream>
using namespace std;
class A{
public:
A(){x=0; cout << "1";}
A(int t) {x=t; cout << "2";}
A(const A& a) {x=a.x; cout << "3";}
const A& operator=(const A& a) {x=a.x; cout << "4"; return *this;}
protected:
int x;
};
class B{
public:
B(const A& a=A()) : y(a) { cout << "5";}
B(const A& b, int u){y=b; k=u; cout << "6";}
protected:
A y; int k;
};
class C : public B{
public:
C(int t=1) {z=t; cout <<"7"; }
C(A x) : B(x) {z=0; cout <<"8";}
C(const B& x) : B(x), a(1){z=0; cout <<"9";}
protected:
A a; int z;
};
int main(){
B b2; cout << endl;
C c0; cout <<endl;
c0 = b2; cout <<endl;
return 0;
}

c0 = b2 prints out 32944 correctly.
c0 = b2 calls c0 = C(b2), y.operator= (4) and a.operator= (4)
C(b2) calls B(b2), A(1) (2) and cout << 9 (9)
B(b2) calls A(b2)
A(b2) calls cout << 3 (3)
From down to up: 3 2 9 4 and your final 4.

Related

making out program output

I try to figure out output of the program without running. I'm stuck some points that first when I put a breakpoint after const A g1; , how come the program print output const A 2 5 ? Second, is B b1(a1); same as B b1 = a1; in this code ? Thirdly, when a B obj is constructed by taking parameter an object of A, as you see A a is private member in A class. The p function doesn't execute. How come? I think it should be executed. The last one, when a B obj is executed(constructed), "const B" string literal should be printed screen out. But, It's printed just for B b1(a1);. Why not also B b2(b1); and B b3 = b2;?
#include <iostream>
using std::cout;
class A {
public:
A(int i = 10){ t = i; f(); p("const A ");}
static void f(){ ++s;}
void g() { ++t; p("func g ");}
void operator++() {p("op++ 1 ");}
void operator++(int) {p("op++ 2 ");}
private:
void p(const char *t) const
{cout << t << s << " "
<< this->t << "\n";
}
int t;
static int s;
};
const A g1; // Global object
int A::s = 0;
class B {
public:
B(A& t) : a(t)
{ cout << "const B\n"; }
private:
A a;
};
class C{
public:
C(B& t) : b(t)
{
cout << "const C\n";
}
private:
B b;
};
void h(A a){
++a;
B b(a);
a++;
}
static C g_c( *(new B( *(new A(5) ) ) ) );
int main(){
cout << "--------\n";
{
A::f();
A a;
a.f(); a.g();
}
cout << "--------\n";
{
A a;
h(a);
}
cout << "--------\n";
{
A a1;
A a2(a1);
A a3 = a1;
a2 = a1;
cout << "--------\n";
B b1(a1);
B b2(b1);
B b3 = b2;
b2 = b1;
cout << "--------\n";
}
cout << "--------\n";
return 0;
}
You cannot put a breakpoint outside a function body. There is nothing there. Your global variables are initialised before main is executed. If you want to break the construction of global A g1 put a breakpoint in A's constructor.
B b1(a1); is indeed the same as B b1 = a1;
The p function does not execute because the new A object is copy constructed. It is not your constructor that gets executed but a copy constructor generated by the compiler. If this copy constructor does not do what you'd like it to do, write your own.
Same answer, the first B object is constructed with your constructor, the others are copy constructed.

Implementing Copy Constructor

I am attempting to add a copy constructor to each in order to run the main function. What I have implemented right now currenrtly prints out "b2.valuea = -858993460 b2.valueb = 10" So it reads valueb correctly but obviously something is going wrong with valuea. Advice?
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
int valuea;
public:
int getValuea() const { return valuea; }
void setValuea(int x) { valuea = x; }
// copy constructor
A() {}
A(const A& original)
{
valuea = original.valuea;
}
};
class B : public A
{
int valueb;
public:
int getValueb() const { return valueb; }
void setValueb(int x) { valueb = x; }
// copy constructor
B(){}
B(const B& original)
{
valueb = original.valueb;
}
};
int main()
{
B b1;
b1.setValuea(5);
b1.setValueb(10);
B b2(b1);
cout << "b2.valuea = " << b2.getValuea() << "b2.valueb = " <<
b2.getValueb() << endl;
}
You are not calling the copy constructor of your base-class in your derived copy constructor.
Change it like:
B(const B& original) : A(original){
valueb = original.valueb;
}
And it will output
b2.valuea = 5
b2.valueb = 10

How to enforce a calling of a moving constructor (C++)?

I have this couple of code-lines:
#include <iostream>
using namespace std;
class A
{
public:
A() noexcept
{
cout << "A::A()" << endl;
}
A(const A&) noexcept
{
cout << "A::A(const A&)" << endl;
}
A(A&&) noexcept
{
cout << "A::A(A&&)" << endl;
}
};
class B
{
public:
B(const A& a) noexcept :
_a(a)
{}
B(A&& a) noexcept :
_a(a)
{}
private:
A _a;
};
int main(int argc, char* argv[])
{
A a;
B b1 = B(a);
B b2 = B(A());
}
They produce this output:
A::A()
A::A(const A&)
A::A()
A::A(const A&)
What need I to do in order to the A::A(A&&) will be called from the B::B(A&&)?
As you can see adding noexcept does not solve this issue.
Although the type of a is an rvalue reference to A, a itself is an lvalue. To retain its rvalue-ness, you need to use std::move:
B(A&& a) noexcept :
_a(std::move(a))
{}

Automatic generation of the move constructor

#include <iostream>
using namespace std;
struct A
{
A() {}
A(const A &a) {
cout << "copy constructor" << endl;
}
A& operator=(const A &a) {
cout << "assigment operator" << endl;
}
A(A &&a) {
cout << "move" << endl;
}
A& operator=(A &&a) {
cout << "move" << endl;
}
};
struct B {
A a;
};
B func() {
B b;
return b;
}
int main() {
B b = func();
}
This prints "copy constructor".
For class B the move constructor and the move assignment operator should be automatic generated correct? But why is it using the copy constructor of class A and not the move constructor?
For me it doesn't print anything at all because the copy/move has been elided. However if I thwart RVO with something like:
extern bool choice;
B func() {
B b1, b2;
if (choice)
return b1;
return b2;
}
Then it prints:
move
It may be that your compiler does not yet implement the automatic generation of the move members.

How do I do a deep copy in c++

I am trying to do a deep copy of class B, but A doesn't get set.
Why does b3->print return a garbage number instead of 1?
From what I understand, b2 and b3 are both pointing to the same A object. but I created a new object on the heap with B's copy constructor. so why are they both still poiting to the same object?
I hope this makes sense.
#include <cstdlib>
#include <iostream>
using namespace std;
class A{
int num;
public:
A(int n):num(n){ cout<< "A "<< num << " constructor" <<endl;}
~A(){ cout<< "A "<< num <<" destructor. " <<endl; }
int print(){
cout<< num<< endl;
}
};
class B{
A *a;
int num;
public:
B(int n):num(n){
a = new A(n);
cout<< "B "<< num <<" constructor" <<endl;
}
~B(){
delete a;
cout<< "B "<< num <<" destructor"<<endl;
}
// Copy contructor
B(const B & b): a(new A(b.num)){
}
<strike>int<\strike> void print(){
cout<< num << endl;
}
int get_num(){
return num;
}
};
int main(int argc, char *argv[])
{
B *b2 = new B(1);
B *b3(b2);
b2->print();
delete b2;
b3->print();
system("PAUSE");
return EXIT_SUCCESS;
}
B *b3(b2); doesn't do what you think.
It's equivalent to B* b3 = b2. The pointers will point to the same location. When you do delete b2;, you're also freeing the memory pointed to by b3.
To do a deep copy, do:
B* b3 = new B(*b2);
There's also undefined behaviour here:
int print(){
cout<< num << endl;
}
because you never return. Change the return type to void.
To get the value expected:
B(const B & b): a(new A(b.num)), num(b.num){
}
Other answers to this question will explain about how pointers work, but you should also understand that not using pointers is a better solution. C++'s default behaviors work well with value semantics. If you hold objects by value then the default copy ctor and assignment operators will do a 'deep copy'.
class B{
A a;
int num;
public:
B(int n): a(n), num(n){
cout<< "B "<< num <<" constructor" <<endl;
}
void print(){
cout<< num << endl;
}
int get_num(){
return num;
}
};
Also, if you do use owning pointers you should usually use smart pointers.
here you are not copying b2
B *b3(b2);
instead you are making b3 point to b2
you should have
B *b3 = new B(*b2);
I think you probably intended to write something like this:
#include <iostream>
class A
{
public:
A(int n) : num_(n) {}
void print() { std::cout << num() << std::endl; }
int num() const { return num_; }
private:
int num_;
};
class B
{
public:
B(int n) : a(n) {}
int num() const { return a.num(); }
private:
A a;
};
int main()
{
B b(1);
B b2 = b; // deep copy
}
As you can see:
B doesn't have its own num_ member. Duplication should be avoided.
There's no need to implement the copy constructor or assignment operator (rule-of-three).
Not need to use new here.
There is no such things as shallow/deep copy in c++. You either have values or pointers/references that get copied, and that fully defines the semantics of the copy operation.