12

Why is the argument of the copy constructor a reference rather than a pointer?

Why can't we use the pointer instead?

Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411
  • 2
    You can write a pointer constructor `Foo::Foo(Foo const *)`, but it's not a _copy_ constructor. Given `Foo a;` a copy construction looks like `Foo b(a);` or `Foo c = a;` (and in C++11 maybe `Foo d{a};`). Now consider `Foo x(&a);` or `Foo y = &a;`, does it look like a _copy_ to you?.. – gx_ Sep 04 '13 at 10:41

6 Answers6

14

There are many reasons:

  1. References cannot be NULL. OK, it's possible to create a NULL reference, but it's also possible to cast a std::vector<int>* into a std::vector<SomeType>*. That doesn't mean such a cast has defined behavior. And neither does creating a NULL reference. Pointers have defined behavior when set to NULL; references do not. References are therefore always expected to refer to actual objects.

  2. Variables and temporaries cannot be implicitly converted into pointers to their types. For obvious reasons. We don't want pointers to temporaries running around, which is why the standard expressly forbids doing it (at least when the compiler can tell you are doing it). But we are allowed to have references to them; these are implicitly created.

  3. Because of point number 2, using pointers rather than references would require every copy operation to use the address-of operator (&). Oh wait, the C++ committee foolishly allowed that to be overloaded. So any copy operation would need to actually use std::addressof, a C++11 feature, to get the address. So every copy would need to look like Type t{std::addressof(v)}; Or you could just use references.

legends2k
  • 31,634
  • 25
  • 118
  • 222
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
9

It's just nomenclature. You can use a pointer as well, but that'd be called a conversion constructor.

If you think about it, it makes sense, because you copy one object to another (ergo the "copy"). Not from a pointer to an object. If it was a pointer, it wouldn't do a copy, because you're not copying the pointer to the object, but rather the object the pointer points to to your object.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 2
    `It's just nomenclature` - I'm disagree with it. If you have conversion constructor - copy constructor will be implicitly defined, that can be not what you want. – ForEveR Sep 04 '13 at 10:41
  • 1
    @ForEveR that's still nomenclature though. Not having the term itself would have made it more verbose, sure, but not impossible. – Luchian Grigore Sep 04 '13 at 11:01
  • It would be nomenclature if both were extraneous names for constructors accepting various params. But this isn't the case `copy constructor` is one of the big three. If you don't define a `conversion constructor` as you call it someone who attempts to use it will likely get a compiler error (might depend on if you use `explicit` or not) , where as a copy constructor will get created for them that could be different from your `conversion constructor`.. Not to mention most any STL or templated function or class interacting is going to expect the `copy constructor` to work properly. – UpAndAdam Oct 10 '13 at 17:59
6

Why should it be a pointer? A null pointer wouldn't make sense. And using a pointer wouldn't allow copying temporaries, so you couldn't do things like:

MyClass
func()
{
    //  ...
    return MyClass(...);
}

You can define a constructor taking a pointer. But it won't be a copy constructor, because it couldn't be used in cases like the above. And it won't inhibit the compiler from generating a copy constructor.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
5

Because this is denied by the standard.

Quoting from C++ draft standard n3376 - section 12.8.2:

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

ForEveR
  • 55,233
  • 2
  • 119
  • 133
1

Because a pointer could be a nullptr which would have to be checked and temporaries can't have pointers to them.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
1

Passing by references ensures an actual object is passed to the copy constructor, whilst a pointer can have NULL value, and make the constructor fail