1

I'm busy with writing a piece of code. The function of the code is the following: I have a class Student. I want to copy the grade from freshman to freshman2. Then I delete freshman, but freshman2 should still hold the grade from freshman. I want/need to do this with a copy constructor. I'm not that familiar with a copy constructor, however. This is what I have uptil now. Can someone please help me with this?

#include <iostream>

using namespace std;

class Student
{
public:
    int *grades;
    int size;

    Student (unsigned int n) {grades = new int[n]; size = n;}
    Student(const int& other);
    ~Student() {delete[] grades;}

    Student(Student &old_student) {}
};

int main()
{
    Student *freshman = new Student(1);
    freshman -> grades[0] = 8;

    Student *freshman2 = new Student(*freshman);
    delete freshman;

    cout << freshman2 -> grades[0] << endl;
}

Thanks in advance guys:)

Hulk
  • 6,399
  • 1
  • 30
  • 52
Earless
  • 173
  • 2
  • 3
  • 9
  • Have a look at this answer describing the [copy-and-swap idiom](http://stackoverflow.com/a/3279550/2700399). – Bart van Nierop Sep 18 '13 at 08:31
  • 2
    Side note: don't get used to use `using namespace std;` everywhere. see [this question](http://stackoverflow.com/q/1452721/2513200) for reasons. – Hulk Sep 18 '13 at 08:37
  • Am I right assuming that this is some kind of homework where using `std::vector` is simply not an option? because otherwise the solution is not to reinvent the wheel. Besides: Why are you dynamically allocating the Students in main instead of just saying `Student freshman(1)` and `Student freshman2(freshman)`? – Grizzly Sep 18 '13 at 08:37
  • another note: there's a `delete freshman2;` missing in the `main`. – risingDarkness Sep 18 '13 at 08:54
  • @Grizzly, indeed its for practicing. I have to do it like this. – Earless Sep 18 '13 at 10:49
  • If that's what you have to do, that's what you have to do, but I sure wish instructors would manage to find exercises that don't teach bad practices along with simple techniques. Why not implement a simple `dynarray` class as an exercise? Why write a `Student` class with a bad design instead? It just makes people think that writing high-level classes that do low-level things themselves is in any way acceptable, when it really shouldn't be. – Sebastian Redl Sep 18 '13 at 12:00

3 Answers3

3

straight forward:

Student(const Student &other)
    : grades(new int[other.size])
    , size(other.size)
{
    std::copy(other.grades, other.grades+other.size, grades);
}

But keep in mind that using actual containers would be a better solution. Also, having public data members is not the best idea for encapsulation. Another slight style thing is that using namespace std; is considered bad practice. Note that I have set the copy constructors argument as const&.

How this works

In the initialisation list I allocate a new int array of the same size as the array in the other Student and copy the other.size into the current (this) Student object. What I have now is an array with garbage inside and its size.

Inside the body of the constructor std::copy now gets the actual grades from otherand copies them to the array I just allocated in the initilisation list. Making a copy like this is called deep copying as opposed to shallow copying.

Aren't those parameters for std::copy pointers and not iterators?

I can use std::copy with pointers, because pointers basically fulfill the requirements of InputIterator and OutputIterator. The beginning of the array I want to copy from is simply the pointer other.grades and I want to copy everything until the end (which is the beginning of the array + its size, utilizing pointer arithmetic), storing the copies in the new grades.

Community
  • 1
  • 1
risingDarkness
  • 698
  • 12
  • 25
  • Okay, first of all it works:) Could you perhaps explain to me why it works? – Earless Sep 18 '13 at 10:47
  • I added an explanation, maybe someone who speaks english natively can make it more readable. I'm just a german trying to communicate ;) – risingDarkness Sep 18 '13 at 12:09
  • It helped me a lot indeed. I still dont get everything, but that will come when I've read it a few times. Thank you for your help:) – Earless Sep 18 '13 at 15:39
0

A copy constructor take a const reference to an object of same type. So if you have:

Student(const Student& other);

How do you think you would set the values of your class using the other parameter?

http://en.wikipedia.org/wiki/Copy_constructor

Aesthete
  • 18,622
  • 6
  • 36
  • 45
  • I'll take the downvote, because I think this is a simple enough question for someone to figure out with less than 5 minutes on Google, and should be closed in my opinion. – Aesthete Sep 18 '13 at 08:33
  • 1
    OK, took it away, maybe you are right ^^ Nevertheless your answer is rather a comment ... – Leo Chapiro Sep 18 '13 at 08:34
  • Yeah i know the declaration of the copy construct. But I didnt know how to use it in my code. So dont judge me or whatsoever please:) – Earless Sep 18 '13 at 10:18
  • I mean, I went through over 8 pages about copy construct, but it still didnt work :) Appreciate your help though – Earless Sep 18 '13 at 10:43
0

A possible copy constructor implementation:

Student(const Student &old_student) {
  size = old_student.size;
  grades = new int[size];
  memcpy(grades, old_student.grades, size * sizeof *grades);
}

See risingDarkness' answer for a more didactic implementation. There are many alternative ways to write it. All correct implementations initialize all data members (e.g. size and grades), and they copy the data from old_student.

The const in the first line makes it much more useful, see Why is the copy-constructor argument const? . But even without the const it's considered a copy constructor.

It looks like a waste of memory to allocate a new array, it would be possible to share the array between the objects, but that would make the destructor much more complex, because the destructor has to decide when to delete the array.

Community
  • 1
  • 1
pts
  • 80,836
  • 20
  • 110
  • 183
  • 1
    I am tempted to downvote for the last line, which is flat out wrong. – Jon Sep 18 '13 at 08:31
  • 1
    @thang: *"A non-template constructor for class `X` is a copy constructor if its first parameter is of type `X&`, `const X&`, `volatile X&` or `const volatile X&`, and either there are no other parameters or else all other parameters have default arguments"*. – Jon Sep 18 '13 at 08:32
  • It is a copy ctor even without the `const`. It just cannot be used to copy from temporaries. Of course, 99.99% of classes out there should declare their copy ctors as taking `const &`. – Angew is no longer proud of SO Sep 18 '13 at 08:32
  • And why use assignments instead of initialisation in the ctor? Or `memcpy` instead of `std::copy`? – Angew is no longer proud of SO Sep 18 '13 at 08:33
  • @thang: Using `memcpy` instead of `std::copy` in code likely to be read by beginners seems pretty wrong to me – Grizzly Sep 18 '13 at 08:35
  • Not to mention manual memory management. But while questionable teaching material, at least `new int[]` and `memcpy` are not wrong per se. – Jon Sep 18 '13 at 08:36
  • Ok, I would like to point out that the last line of the code is "}"! There is nothing wrong with "}"! But while we're commenting on the line before last, size * sizeof *grades, while correct, looks misleading. – thang Sep 18 '13 at 08:38
  • I've fixed my answer, please consider reverting your downvote if you don't see anything wrong with it. – pts Sep 18 '13 at 08:43
  • @pts: I didn't downvote, but most of the points mentioned (`memcpy`, assignment instead of initialization) still remain, so there is still plenty of wrong with it – Grizzly Sep 18 '13 at 08:55