Copy constructors - making deep copies

Mar 9, 2010 at 5:53am
EDIT: Nevermind. I got it.

-----

I'm sorry for making another topic, but my brain just went kapowie!; plus I've burned myself out from studying for my midterm tomorrow.

For my copy constructor, I honestly don't think I'm doing this right...is there a workaround OTHER than using the function provided in the <algorithm> library? Otherwise, I guess I'll have to resort to it.

My program crashes when I execute it and I'm guessing it's due to the copy constructor. (I'm also only posting smaller portions of my code to save your eyes.)

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstdlib>
#include "stringArray.h"

using namespace std;

int main( )
{
stringArray sa1, sa2(100);

sa1.addString("abcdefg");
sa1.addString("lmnopq");
sa1.printStringArray( );
sa2.addString("1234");

// This line causes the crash
stringArray sa3(sa1);
return EXIT_SUCCESS;
}



stringArray.cpp
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
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include "stringArray.h"

using namespace std;

// Constructor
stringArray::stringArray (const size_t max_size)
{
	// Sets the number of items/data in the bag to 0
	count = 0;
	// Sets the bag's capacity size to whatever the parameter is
	capacity = max_size;
	// Dynamically creates space for strings in the bag
	data = new stringArray::str[max_size];
}



// Copy constructor
stringArray::stringArray (const stringArray& source)
{
	// Assigns all member values to whatever
	count = source.count;
	capacity = source.capacity;

	// Maybe call the overload function? (=)
	// std::copy(source.data, source.data + source.count, data);

	for (int i = 0; i < capacity; i++)
	{
	    data[i] = source.data[i];
	}
}



stringArray.h
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
#ifndef STRINGARRAY_H_INCLUDED
#define STRINGARRAY_H_INCLUDED

class stringArray
{
    public:
        // Constructor and a copy constructor
        stringArray (const size_t max_size = DEFAULT_SIZE);
        stringArray (const stringArray& source);
        // Destructor
        ~stringArray();

        // Adds a new string in the bag
        // Returns true if successful; false otherwise
        bool addString(const char new_string[ ]);

        // Removes one occurrence of old_string from the bag
        // Returns true if successful; false otherwise
        bool removeString(const char old_string[ ]);

        // Removes all occurrences of old_string from the bag
        // Returns number of strings removed
        // May need to be changed to an int
        size_t removeAll(const char old_string[ ]);

        // Substitutes/replaces one occurrence of old_string with new_string
        // Returns true if successful; false otherwise
        bool substitute(const char old_string[ ], const char new_string[ ]);

        // Substitutes/replaces all occurrences of old_string with new_string
        // Returns number of strings replaced
        size_t substituteAll(const char old_string[ ], const char new_string[ ]);



        // Returns total number of strings in the bag
        size_t size( ) const;

        // Returns true of cur_string is in the bag; false if not
        bool is_string(const char cur_string[ ]) const;

        // Returns number of occurrences of cur_string
        size_t occurrences(const char cur_string[ ]) const;

        // Prints out all strings in the object
        // One string per line
        void printStringArray( ) const;

        // Prints all strings out in the object
        // One string per line
        // Sorted order from least to greatest
        void printSortedStringArray( ) const;



        // Sets the default_size/capacity of the bag to 20
        static const size_t DEFAULT_SIZE = 20;

        // Typedef stuff
        typedef const char* str;

    private:
        // Member variables here
        // count = The number of items in the bag
        size_t count;
        // capacity = The number of items that can be stored in the bag
        size_t capacity;
        // data = The item in the bag
        str* data;
};

#endif // STRINGARRAY_H_INCLUDED 
Last edited on Mar 10, 2010 at 6:03am
Mar 9, 2010 at 6:28am
You aren't allocating any memory for your data inside the copy constructor. Hence, data[i] has a high probability of crashing your program.
Mar 9, 2010 at 6:29am
I realized that, but how do I go about fixing it? That's what I'm having trouble with. I know it's got to do something with dereferencing it, but at the same time, I don't know how it should look.
Mar 9, 2010 at 6:37am
It doesn't actually have anything to do with dereferencing. You would have to use new, like you did in your other constructor that takes the size as a parameter. You would just be getting the size from a different variable now instead.
Mar 9, 2010 at 6:52am
So would it be something like...:

1
2
3
4
5
data = new stringArray::str[DEFAULT_SIZE];
for (int i = 0; i < capacity; i++)
	{
	    data[i] = source.data[i];
	}


?
Mar 9, 2010 at 1:14pm
You should allocate the same number of elements as the source container has (capacity?).

You should not prefix str with stringArray:: when writing code inside stringArray; this is not standard.

You can use std::copy() instead of the for() loop.
Mar 9, 2010 at 4:05pm
But what if I wanted to add more items to the container that I'm creating? Hence why I'm filling it up to the container's capacity. Count is just how many items the container has, and capacity is...well, capacity.

My TA suggested this in recitation last time, so that's why I included it in my code.

Also, as I said earlier...I don't think we're allowed to use std::copy(). This is why I'm asking for the algorithm for this.
Last edited on Mar 9, 2010 at 4:12pm
Mar 9, 2010 at 4:31pm
If you want to add more, you would allocate more memory later. When you are copy constructing it, you know how many elements you need to have.
Mar 9, 2010 at 8:26pm
I got it. Thanks.

I actually found out that my copy constructor isn't causing my program to crash...it's the constructor that's causing it to crash. I think I was looking at the wrong line last night.

Help again, is appreciated.
Mar 10, 2010 at 12:12am
I don't see how the constructor could cause a crash. The typedef that you have made is extraordinarily confusing. I recommend that you delete that typedef and just refer to char*. it took me a few minutes to figure out what in the heck the str type is.

Designing a custom string class was a challenge for some of the greatest programmers in the world. Good luck. You've got a long way to go.
Mar 10, 2010 at 6:01am
I found out what was wrong. I think it was in my destructor because I forgot to comment something else out.

I actually have been using a typedef, hence line 60 in stringArray.h.
Mar 10, 2010 at 6:20am
Yeah, his point was that it was confusing to have that there. IMHO, char* doesn't really need to be typedef'd, although if you REALLY wanted to I would call it c_string or something to make it obvious it isn't related to std::string.
Topic archived. No new replies allowed.