Pejman Moghadam / C-programming

C++ - Assignment operator overloading and copy constructor

Public domain


#include <iostream>
using namespace std;

class test_1 {
    int c;
public:
    // Constructor
    test_1(int i) : c(i)
    { /* Empty */ }

    // Copy constructor
    test_1(const test_1 &ob)
    {
            cout << "Copy contructor.\n";
            c = ob.c;
    }

    // Assignment overload
    test_1 operator=(test_1 op2)  // Difference between two classes
    {
            cout << "Overloaded assignment.\n";
            c = op2.c;
            return *this;
    }

    void show() { cout << c << endl; }
};

class test_2 {
    int c;
public:
    // Constructor
    test_2(int i) : c(i)
    { /* Empty */ }

    // Copy constructor
    test_2(const test_2 &ob)
    {
            cout << "Copy contructor.\n";
            c = ob.c;
    }

    // Assignment overload
    test_2 &operator=(test_2 &op2)  // Difference between two classes
    {
            cout << "Overloaded assignment.\n";
            c = op2.c;
            return *this;
    }

    void show() { cout << c << endl; }
};

int main()
{
    {
            test_1 obj1(100);
            test_1 obj2(200);

            obj1 = obj2;

            obj1.show();
            obj2.show();
    }

    cout << endl;

    {
            test_2 obj1(100);
            test_2 obj2(200);

            obj1 = obj2;

            obj1.show();
            obj2.show();
    }

    return 0;
}

#include <iostream>
using namespace std;

class test_c {
    int c;
public:
    // Constructor
    test_c(int i=0) : c(i)
    { /* Empty */ }

    // Assignment overload
    test_c operator=(test_c op2)  // Difference between two classes
    {
            cout << "Overloaded assignment.\n";
            c = op2.c;
            // return *this;
    }

    void show() { cout << c << endl; }
};

test_c f()
{
    test_c ob(100);
    return ob;
}

int main()
{
    test_c obj;
    obj = f();
    obj.show();

    return 0;
}

// g++ --no-elide-constructors 2.cpp && ./a.out
// http://en.wikipedia.org/wiki/Return_value_optimization
// http://en.wikipedia.org/wiki/Copy_elision
#include <iostream>
using namespace std;

class test_c {
    int c;
public:
    // Constructor
    test_c(int i=0) : c(i)
    { /* Empty */ }

    // Assignment overload
    test_c &operator=(test_c op2)
    {
            cout << "Overloaded assignment.\n";
            c = op2.c;
            return *this;
    }

    // Copy constructor
    test_c(const test_c &ob)
    {
            cout << "Copy contructor.\n";
            c = ob.c;
    }

    void show() { cout << c << endl; }
};

test_c f()
{
    test_c obj2(200);
    return obj2;
}

int main()
{
    {
            test_c obj1(100);
            test_c obj2(200);
            obj1 = obj2;
            obj1.show();
    }

    cout << endl;

    {
            test_c obj1(100);
            obj1 = f();
            obj1.show();
    }

    return 0;
}

#include <iostream>
using namespace std;

class foo {
public:
  foo() { cout << "foo::foo()\n"; }
  foo( const foo& ){ cout << "foo::foo( const foo& )\n"; }
  ~foo(){ cout << "foo::~foo()\n"; }
};

foo bar(){ foo local_foo; return local_foo; }

int main()
{
  foo f = bar();
}

/* This program demonstrates that GCC 4.1 does Named return value optimization, 
 * i.e. it omits creating a temporary object in a function returning an object if 
 * all return statements in the function return the same local variable.
 */

#include <iostream>
using namespace std;

class C {
 public:
  C() { cout << "+\n" ; }
  ~C() { cout << "-\n"; }
  C(const C&) { cout << ":\n"; }
  C& operator=(const C&) { cout << "=\n"; }
};

C F(int i) {
  C x;
  if (i > 1) {
    return x;
  } else {
    return x;
  }
}

C G(int i) {
  if (i > 1) {
    C x;
    return x;
  } else {
    C y;
    return y;
  }
}

int main(int argc, char**)
{
  F(argc);
  cout << "~~~\n";
  G(argc);
  return 0;
}

#include <iostream>
using namespace std;

class test_c {
    int *p;
public:
    test_c(int i=0)
    {
            cout << "Constructor.\n";
            p = new int [1];
            *p = i;
    }

    ~test_c()
    {
            cout << "Destructor.\n";
            delete [] p;
    }

    test_c(const test_c &ob)
    {
            cout << "Copy contructor.\n";
            p = new int [1];
            *p = *(ob.p);
    }

    test_c operator=(test_c op2)
    {
            cout << "Overloaded assignment.\n";
            *p = *(op2.p);
            return *this;
    }

    void show() 
    { 
            cout << *p << endl; 
    }
};

test_c f()
{
    cout << "Function called.\n";
    test_c ob(100);
    return ob;
}

int main()
{
    test_c obj;
    obj = f();
    obj.show();

    return 0;
}

#include <iostream>
#include <cstring>
using namespace std;

class test_c {
    char *s;
public:
    test_c()
    {
            s = new char('\0');
    }

    test_c(char *str)
    {
            cout << "Constructor.\n";
            s = new char [strlen(str)+1];
            strcpy(s, str);
    }

    ~test_c()
    {
            cout << "Destructor.\n";
            delete [] s;
    }

    test_c(const test_c &ob)
    {
            cout << "Copy contructor.\n";
            s = new char [strlen(ob.s)+1];
            strcpy(s, ob.s);
    }

    test_c operator=(test_c op2)
    {
            cout << "Overloaded assignment.\n";
            if (strlen(s) < strlen(op2.s)) {
                    delete [] s;
                    s = new char [strlen(op2.s)+1];
            }
            strcpy(s, op2.s);
            return *this;
    }

    void show()
    { 
            cout << "Show: " << s << endl;
    }
};

test_c f()
{
    char s1[80];
    cout << "Enter a string: ";
    cin >> s1;

    test_c ob(s1);
    return ob;
}

int main()
{
    test_c obj;
    obj = f();
    obj.show();

    return 0;
}

#include <iostream>
#include <cstring>
using namespace std;

const int MAXLEN = 80;

class STR {
    char string[MAXLEN];
public:
    STR(const char *s = "");
    STR(const STR &s);
    STR operator=(STR s);
    STR operator=(const char *cs);
    STR operator+(STR s);
    STR operator+(const char *cs);
    friend STR operator+(const char *cs, STR s);
    void show();
};

STR::STR(const char *s)
{
    cout << "[cnstr] ";
    strcpy(string, s);
}

STR::STR(const STR &s)
{
    cout << "[cpycnstr] ";
    strcpy(string, s.string);
}

STR STR::operator=(STR s)
{
    cout << "[=obj] ";
    strcpy(string, s.string);
    return *this;
}

STR STR::operator=(const char *cs)
{
    cout << "[=cs] ";
    strcpy(string, cs);
    return *this;
}

STR STR::operator+(STR s)
{
    cout << "[+obj] ";
    STR temp;
    strcpy(temp.string, string);
    strcat(temp.string, s.string);
    return temp;
}

STR STR::operator+(const char *cs)
{
    cout << "[+cs] ";
    STR temp;
    strcpy(temp.string, string);
    strcat(temp.string, cs);
    return temp;
}

STR operator+(const char *cs, STR s)
{
    cout << "[cs+] ";
    STR temp;
    strcpy(temp.string, cs);
    strcat(temp.string, s.string);
    return temp;
}

void STR::show()
{
    cout << string << endl;
}

int main()
{

    // [cnstr] Hello world.
    {
            // [cnstr]
            STR s1("Hello world.");

            s1.show();
    }

    // [cnstr] [cpycnstr] [cpycnstr] [=obj] [cpycnstr] Hello world.
    {
            // [cnstr]
            STR s1 = "Hello world.";

            // [cpycnstr]
            STR s2 = s1;

            // [cpycnstr] [=obj] [cpycnstr]
            s2 = s1;

            s2.show();
    }

    // [cnstr] [cnstr] [cnstr] [cpycnstr] [=obj] [cpycnstr] [=obj] [cpycnstr] Hello world.
    // Hello world.
    // Hello world.
    {
            // [cnstr]
            STR s1("Hello world.");

            // [cnstr] [cnstr]
            STR s2, s3;

            // [cpycnstr] [=obj] [cpycnstr] [=obj] [cpycnstr]
            s3 = s2 = s1;

            s1.show();
            s2.show();
            s3.show();
    }

    // [cnstr] [cnstr] [=cs] [cpycnstr] [=obj] [cpycnstr] Hello world.
    // Hello world.
    {
            const char s1[] = "Hello world.";

            // [cnstr] [cnstr]
            STR s2, s3;

            // [=cs] [cpycnstr] [=obj] [cpycnstr]
            s3 = s2 = s1;

            s2.show();
            s3.show();
    }

    // [cnstr] [cnstr] [cnstr] [cpycnstr] [+obj] [cnstr] [=obj] [cpycnstr] Hello world.
    {
            // [cnstr]
            STR s1("Hello ");

            // [cnstr]
            STR s2("world.");

            // [cnstr]
            STR s3;

            // [cpycnstr] [+obj] [cnstr] [=obj] [cpycnstr]
            s3 = s1 + s2;

            s3.show();
    }

    // [cnstr] [cnstr] [+cs] [cnstr] [=obj] [cpycnstr] Hello world.
    {
            // [cnstr]
            STR s1("Hello ");

            const char s2[] = "world.";

            // [cnstr]
            STR s3;

            // [+cs] [cnstr] [=obj] [cpycnstr]
            s3 = s1 + s2;

            s3.show();
    }

    // [cnstr] [cnstr] [cpycnstr] [cs+] [cnstr] [=obj] [cpycnstr] Hello world.
    {
            const char s1[] = "Hello ";

            // [cnstr]
            STR s2("world.");

            // [cnstr]
            STR s3;

            // [cpycnstr] [cs+] [cnstr] [=obj] [cpycnstr]
            s3 = s1 + s2;

            s3.show();
    }

    return 0;
}

Book

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;

class test_c {
    char *s;
public:
    // Normal constructor
    test_c()
    {
            cout << "Constructor.\n";
            s = new char('\0'); // s points to a null string.
    }

    // Copy constructor
    test_c(const test_c &ob)
    {
            cout << "Copy constructor.\n";
            s = new char[strlen(ob.s)+1];
            strcpy(s, ob.s);
    }

    // Destructor
    ~test_c()
    {
            cout << "Destructor.\n";
            delete [] s;
    }

    // Overloading assignment 
    test_c operator=(test_c ob)
    {
            cout << "Assignment.\n";
            if(strlen(s) < strlen(ob.s)) {
                    cout << "Delete.\n";
                    delete [] s;
                    s = new char[strlen(ob.s)+1];
            }
            strcpy(s, ob.s);
            return *this;
    }

    // Load a string.
    void set(char *str)
    {
            s = new char[strlen(str)+1];
            strcpy(s, str);
    }

    void show() 
    { 
            cout << s << "\n"; 
    }

};

// Return an object of type test_c.
test_c input()
{
    char instr[80];
    test_c str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);
    return str;
}

int main()
{
    test_c ob;

    // assign returned object to ob
    ob = input(); // This is now OK
    ob.show();

    return 0;
}

Mine

#include <iostream>
#include <cstring>
using namespace std;

class test_c {
    char *s;
public:
    test_c()
    {
            cout << "Constructor.\n";
            s = new char('\0');
    }

    ~test_c()
    {
            cout << "Destructor.\n";
            delete [] s;
    }

    test_c &operator=(test_c op2)
    {
            cout << "Overloaded assignment.\n";
            delete [] s;
            s = new char[strlen(op2.s)+1];
            strcpy(s, op2.s);
            return *this;
    }

    void set(char *str)
    {
            cout << "Set: Delete.\n";
            delete [] s;
            s = new char[strlen(str)+1];
            strcpy(s, str);
    }

    void show()
    {
            cout << "Show: ";
            cout << s << endl;
    }

};

test_c input()
{
    char str[80];
    cout << "Enter a string : ";
    cin >> str;

    test_c ob;
    ob.set(str);

    return ob;
} 

int main()
{
    test_c obj;
    obj = input();
    obj.show();

    return 0;
}

12.8.15

When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):

-- in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function's return value

-- when a temporary class object that has not been bound to a reference (12.2) would be copied to a class object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary object directly into the target of the omitted copy


BY: Pejman Moghadam
TAG: overloading
DATE: 2013-03-25 01:47:37


Pejman Moghadam / C-programming [ TXT ]