Copy Constructor issue?

I have a class which does not have copy constructor or operator= overloaded. The code is pretty big but the issue is around this pseudo-code:

1
2
3
4
5
6
7
ClassA object1(x,y); 

object1.add(z) ;
myVector.push_back(object1);  
//Now when I retrieve from myVector and do add it 
// apparently creates another object 
myVector.at(index).add(z1); 


Like I said it is pseudo-code. I hope it make sense to experts out there!
Do i need copy constructor or is there a better solution?
Thanks in advance
I have not understood where is new object created?! Function at() returns the refernce to an object so none object is created.
I think new object is created during push_back.

Another thing to note. So far, the ClassA only had basic types and vector<int> as data type. Therefore, i was not facing the issue all this while without me having copy constructor or = defined. In this release we now included a new user-defined ClassB as data member. Maybe this new data member enforces me to create my copy constructo?
closed account (zb0S216C)
Jay23 wrote:
Do i need copy constructor or is there a better solution?

Define a copy-constructor only if your class contains dynamically allocated memory or if it inherits from another class. Otherwise, there's no need to overload it. For example:

1
2
3
4
5
6
7
8
9
10
11
12
struct Object_A
{
    Object_A(void) : A(0), B(false) { }
    int A;
    bool B;
};

struct Object_B
{
    Object_B(void) : Memory(new int(0)) { }
    int *Memory;
};

In Object_A, there's no need for a copy constructor because the compiler can handle those types with member-wise copies. However, Object_B does require a copy constructor because of the memory allocated by Object_B::Memory.

Note that the use of the assignment operator (Object.operator = (...)) invokes the copy constructor. Also note that a copy-constructor requires a constant reference to the same type, with no other parameters. Finally, note that the compiler will only provide a copy constructor if your object requires it. For instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Code A
class Object;

int main(void)
{
    ::Object X, Y;
    
    return(0);
}

// Code B
class Object;

int main(void)
{
    ::Object X, Y(X);
    
    return(0);
}

Here, in Code A, the compiler will not generate a copy constructor because it didn't need it. However, in Code B, the compiler will generate a copy constructor because Y used X to initialise itself.

Wazzak
Last edited on
Thanks so let's say my ClassA looks like

1
2
3
4
5
6
7
8
9
10
11
Class ClassA {

private:
    int x;
    string y;
    ClassB b;
    vector<int> i;
public:
    int z;

}


will i need copy constructor because it has ClassB
closed account (zb0S216C)
Yes. You need to invoke the copy constructors of members y, b and i.

Edit:

Compile these code samples and see the reason why:

Code A:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Base
{
    Base(void) : X(0) { }
    Base(const Base &pBase) : X(pBase.X) { std::cout << "Base::CCtor()\n"; }
    protected:
        int X;
};

struct Test : public ::Base
{
    Test(void) : ::Base(), Y(X) { }
    Test(const Test &pTest) : Y(0) { std::cout << "Test::CCtor()\n"; }

    int Y;
};

int main(int argc,char *argv[])
{
    ::Test X, Y(X);

    std::cin.ignore( std::numeric_limits< std::streamsize >::max( ), '\n' );
    return( 0 );
}

Code B:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct Base
{
    Base(void) : X(0) { }
    Base(const Base &pBase) : X(pBase.X) { std::cout << "Base::CCtor()\n"; }
    protected:
        int X;
};

struct Test : public ::Base
{
    Test(void) : ::Base(), Y(X) { }
    Test(const Test &pTest) : ::Base(pTest), Y(0) { std::cout << "Test::CCtor()\n"; }

    int Y;
};

int main(int argc,char *argv[])
{
    ::Test X, Y(X);

    std::cin.ignore( std::numeric_limits< std::streamsize >::max( ), '\n' );
    return( 0 );
}


Wazzak
Last edited on
Yes. You need to invoke the copy constructors of members y, b and i.


No, he doesn't.

The compiler generated copy constructor will do the right thing. Consider a more realistic example (note that the derived class defines no copy constructor and no assignment operator but somehow everything still magically works.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <vector>
#include <iostream>
#include <string>

class class_that_requires_cc
{
	unsigned n_size ;
	int * n ;

	void copy(const class_that_requires_cc& c)
	{
		n_size = c.n_size ;
		n = new int[n_size] ;

		for (unsigned i=0; i<n_size; ++i)
			n[i] = c.n[i] ;
	}

public:

	class_that_requires_cc()
		: n_size(10), n(new int[n_size]) {} 

	class_that_requires_cc(const class_that_requires_cc& c)
	{ 
		std::cout << "base cc\n";
		copy(c); 
	}

	virtual ~class_that_requires_cc() { delete [] n; }

	class_that_requires_cc& operator=(const class_that_requires_cc& c)
	{
                std::cout << "base operator=\n" ;
		if ( this == &c)
			return *this ;
		delete [] n ;
		copy(c) ;
		return *this ;
	}

	unsigned size() const { return n_size; }

	int& operator[](unsigned idx) { return n[idx]; }
};

class derived : public class_that_requires_cc
{
     std::string name ;

public:

	derived(std::string x) : class_that_requires_cc(), name(x) {}

	std::string GetName() const { return name; }

};


int main()
{
	derived x( "Arnold" ) ;
	derived z( "Avery" ) ;

	for ( unsigned i =0; i < x.size() ; ++i )
	{
		x[i] = i ;
		z[i] = i*2 ;
	}

	derived y(x) ;

	std::cout << y.GetName() << '\n' ;
	for ( unsigned i=0; i < y.size() ; ++i )
		std::cout << y[i] << ' ' ;
	std::cout << '\n' ;

	x = z ;	
	
	std::cout << x.GetName() << '\n' ;
	for ( unsigned i=0; i < x.size() ; ++i )
		std::cout << x[i] << ' ' ;
	std::cout << '\n' ;
}








Last edited on
Topic archived. No new replies allowed.