13

On page 6 of Scott Meyers's Effective C++, the term 'copy constructor' is defined. I've been using Schiltdt's book as my reference and I can find no mention of copy constructors. I get the idea but is this a standard part of c++? Will such constructors get called when a pass a class by value?

John Feminella
  • 303,634
  • 46
  • 339
  • 357
Mike D
  • 2,753
  • 8
  • 44
  • 77
  • 12
    Well, that would be typical of Schildt - why on earth do people use his books? –  Jan 30 '10 at 14:39
  • 4
    Please, don't take Schildt's books without a grain of salt. Google for the term "Bullschildt" and see for yourself. More seriously, read reviews of Schildt's books on ACCU; most of them are not favourable. – C. K. Young Jan 30 '10 at 14:39
  • 1
    @Neil: although I've also heard bad things about Schildt's books, it's *simply hard to believe* that it doesn't talk about copy constructors. – Eli Bendersky Jan 30 '10 at 14:41
  • 1
    Don't use Schildt's books. Try Accelerated C++, §11.3. You'll thank me later. – jason Jan 30 '10 at 14:44
  • 1
    In my experience, Schildt books see C++ as 'C with extra pieces', rather than a new language that is derived from C, so he often misses the point with features like this. Try James B Coplien's 'C++ Style and Idioms' for comparison. – JBRWilkinson Jan 31 '10 at 11:28

7 Answers7

16

Yes, copy constructors are certainly an essential part of standard C++. Read more about them (and other constructors) here (C++ FAQ).

If you have a C++ book that doesn't teach about copy constructors, throw it away. It's a bad book.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
13

A copy constructor has the following form:

class example 
{
    example(const example&) 
    {
        // this is the copy constructor
    }
}

The following example shows where it is called.

void foo(example x);

int main(void)
{
    example x1; //normal ctor
    example x2 = x1; // copy ctor
    example x3(x2); // copy ctor

    foo(x1); // calls the copy ctor to copy the argument for foo

}
DerKuchen
  • 1,840
  • 1
  • 15
  • 15
  • 2
    Only if `foo` has the prototype `void foo(example x);`. For instance, `void foo(const example& x);` won't call any constructors. Or `void foo(int x);` which may call a cast operator `operator int()` if not a compiler error. – kennytm Jan 30 '10 at 19:48
  • 1
    I've edited the post to include the prototype for foo(), to make it clear. – DerKuchen Jan 31 '10 at 11:02
  • 1
    -1 "A copy constructor has the following form:" is incorrect. There are four possible forms of copy constructor. In addition the class example is syntactically invalid. – Cheers and hth. - Alf May 23 '14 at 13:48
  • A constructor is the copy constructor if its first parameter is a reference to the class type and any additional parameters have default values. – kgf3JfUtW Oct 02 '16 at 03:25
4

Copy constructor will be called in then following scenarios:

  • When creating new objects from an existing object.

    MyClass Obj1;
    MyClass Obj2 = Obj1; // Here assigning Obj1 to newly created Obj2
    

    or

    MyClass Obj1;
    MyClass Obj2(Obj1);
    
  • When passing class object by value.

    void NewClass::TestFunction( MyClass inputObject_i )
    {
      // Function body
    }
    

    Above MyClass object passed by value. So copy constructor of MyClass will call. Pass by reference to avoid copy constructor calling.

  • When returning objects by value

    MyClass NewClass::Get()
    {
      return ObjMyClass;
    }
    

    Above MyClass is returned by value, So copy constructor of MyClass will call. Pass by reference to avoid copy constructor calling.

Mat
  • 202,337
  • 40
  • 393
  • 406
FebinDonz
  • 431
  • 4
  • 6
4

See Copy constructor on Wikipedia.

The basic idea is copy constructors instantiate new instances by copying existing ones:

class Foo {
  public:
    Foo();                // default constructor
    Foo(const Foo& foo);  // copy constructor

  // ...
};

Given an instance foo, invoke the copy constructor with

Foo bar(foo);

or

Foo bar = foo;

The Standard Template Library's containers require objects to be copyable and assignable, so if you want to use std::vector<YourClass>, be sure to have define an appropriate copy constructor and operator= if the compiler-generated defaults don't make sense.

Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
2

A copy constructor is a constructor which does deep copy. You should write your own copy constructor when there is a pointer type variable inside the class. Compiler will insert copy constructor automatically when there is no explicit copy constructor written inside the code. The type of a copy constructor parameter should always be reference type, this to avoid infinite recursion due to the pass by value type.

below program explains the use of copy constructor

#include <iostream>
#pragma warning(disable : 4996)
using namespace std;
class SampleTest {
private:
    char* name;
    int age;
public:   
    SampleTest(char *name1, int age) {
        int l = strlen(name1);
        name = new char[l + 1];
        strcpy(this->name, name1);
        this->age = age;
    }
        SampleTest(const SampleTest& s) { //copy constructor 
            int l = strlen(s.name);
            name = new char[l + 1];
            strcpy(this->name, s.name);
            this->age = s.age;
        }
    void displayDetails() {
        cout << "Name is " << this->name << endl;
        cout << "Age is " << this->age << endl;
    }
    void changeName(char* newName) {
        int l = strlen(newName);
        name = new char[l + 1];
        strcpy(this->name, newName);
    }
};
int main() {
    SampleTest s("Test", 10);
    s.displayDetails();
    SampleTest s1(s);
    cout << "From copy constructor" << endl;
    s1.displayDetails();
    s1.changeName("Test1");
    cout << "after changing name s1:";
    s1.displayDetails();
    s.displayDetails();
    cin.get();
    return 0;
}
  • If using the **this** pointer to show that you address a member variable you should do it also with `this->name = new char[l + 1];` for better readability. At a first glance I stumbled about it. – Ingo Mar 18 '23 at 17:04
1

The C++ FAQ link posted by Eli is nice and gbacon's post is correct.

To explicitly answer the second part of your question: yes, when you pass an object instance by value the copy constructor will be used to create the local instance of the object in the scope of the function call. Every object has a "default copy constructor" (gbacon alludes to this as the "compiler generated default") which simply copies each object member - this may not be what you want if your object instances contain pointers or references, for example.

Regarding good books for (re)learning C++ - I first learned it almost two decades ago and it has changed a good deal since then - I recommend Bruce Eckel's "Thinking in C++" versions 1 and 2, freely available here (in both PDF and HTML form):

http://www.ibiblio.org/pub/docs/books/eckel/

Peter
  • 2,526
  • 1
  • 23
  • 32
1

Copy Constructor is an essential part of C++. Even-though any C++ compiler provides default copy constructor if at all if we don't define it explicitly in the class, We write copy constructor for the class for the following two reasons.

  1. If there is any dynamic memory allocation in the class.
  2. If we use pointer variables inside the class. (otherwise it will be a shallow copy in which 2 objects will point to the same memory location.)

To make a deep copy, you must write a copy constructor and overload the assignment operator, otherwise the copy will point to the original, with disastrous consequences.

The copy constructor syntax would be written as below:

class Sample{

public:
   Sample (const Sample &sample);

};

int main()
{

   Sample s1;
   Sample s2 = s1;   // Will invoke Copy Constructor.
   Sample s3(s1);     //This will also invoke copy constructor.

   return 0;
}
McDowell
  • 107,573
  • 31
  • 204
  • 267
Shivaraj Bhat
  • 841
  • 2
  • 9
  • 20