3

I met a quiz saying that the code below is ill-formed because "It is illegal to have a constructor whose first and only non-default argument is a value parameter for the class type."

I couldn't understand that. Why things like A(A a) : val (a.val) {} is ruled as illegal? why such a line in the standard? Is it because this will lead to ambiguity with copy constructor?

#include <iostream>

struct A
{
  A() : val() {}
  A(int v) : val(v) {}
  A(A a) : val(a.val) {} 

  int val;
};

int main(int argc, char** argv)
{
  A a1(5);
  A a2(a1);

  std::cout << a1.val + a2.val << std::endl;

  return 0;
}
athos
  • 6,120
  • 5
  • 51
  • 95

3 Answers3

7

A(A a) : val(a.val) {} will cause an infinite recursion because constructor arguments are being copied by value (invoking copy constructor and again the copy constructor and ...)

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
3

A copy constructor is called when an object is passed by value. Copy constructor itself is a function. So if we pass argument by value in a copy constructor, a call to copy constructor would be made to call copy constructor which becomes a non-terminating chain of calls. Therefore compiler doesn’t allow parameters to be pass by value

Its already discussed on this SO post Why should the copy constructor accept its parameter by reference in C++?

Community
  • 1
  • 1
Ankur
  • 3,584
  • 1
  • 24
  • 32
1

Everything changes with const:

#include <iostream>

struct A
{
    A () : _a(0) {}
    A (int a) : _a(a) {}
    A (const A& a) : _a(a._a) {}
    int _a;
};

int main()
{
    A a(5);
    A b(10);
    A c(a);

    std::cout << a._a + b._a + c._a << std::endl; // 20
    return 0;
}
Joel
  • 1,805
  • 1
  • 22
  • 22