2

I was reading some C++ code from a basic CPU emulator and I just can't understand this:

class CPU {
private:
    CPU (const CPU&){}
};

I understand pointers, I also checked this: Ampersand & with const in constructor. Apparently it is a (hard) copy constructor, but I don't understand, how does this work? why const? Why the ampersand in the end without a var name? Why private? I haven't found an example like this in my books or cplusplus.com.

On a side note:

int foo(int var)  { cout << var; }
int bar(int &var) { cout << var; }

foo and bar print the same thing? bar is essentially printing *&var?

Any help is appreciated!

Community
  • 1
  • 1
ShadoWalkeR
  • 123
  • 1
  • 8

4 Answers4

3

It doesn't work. The operative word here is private. What this whole construct does is create a copy constructor which could only be invoked from a member function, effectively disabling that behavior. Normally people would leave out the function body so that you'd get a link error too if you invoked it from a member function.

In C++11 parlance this would be implemented as

CPU(const CPU&) = delete;

If you actually tried to induce it:

CPU x;
CPU y(x); // this is the one that matches the parameters

you would get a compiler error, because you're not a member function but you're trying to invoke a private function.

The reason they've done this is because they want to disable the functionality - you can't create one of these objects using a copy constructor.

The "const CPU&" means "take a reference to a const CPU". Leaving out the variable name is legal because the function never references it, but it has to match the argument pattern.

kfsone
  • 23,617
  • 2
  • 42
  • 74
  • Actually it 'can work' if other CPU methods make use of the copy constructor (though it's not likely the case) – Pyrce Nov 26 '13 at 23:52
  • @Pyrce: That is why usually the body is not defined. So if it is accidentally used then you get a linker error. But that is why `=delete` is better since you don't have to remember not to define it. – Martin York Nov 26 '13 at 23:54
  • What do you mean it doesn't work? it seems to be code in existing project, and most C++ projects are still written in C++03 the best case, where this is the way to hide copy constructor from other classes. – Iuri Covalisin Nov 27 '13 at 00:03
  • Useful information didn't know you could prevent copying like that. @IuriCovalisin main in this code does not use the copy ctor. Thanks. – ShadoWalkeR Nov 27 '13 at 00:03
  • @ShadoWalkeR: main cannot use copy ctor - this is the purpose of making it private, to make compiler fail if somebody tries to call it. – Iuri Covalisin Nov 27 '13 at 00:13
  • Giving it an empty function body is usually someone getting it wrong. That provides the wrong implementation (does nothing, leaves the constructed object uninitialized), and if you access the function inside a member function by mistake, you'll get no warning, just random bugs. – kfsone Nov 27 '13 at 01:46
1

The & indicates pass by reference when used in argument definitions. This converts the argument into a pointer and de-references that pointer when you use it within the function scope. In your second question both functions print the same thing because the & simply says pass the original object by reference instead of copying it into the function header. The same content exists, the only difference is one of the functions copies the full input and the other could edit the source variable if it wanted to.

CPU (const CPU&){} is saying the constructor requires a constant reference to a CPU object. This means you can only access const functions of CPU (and guarentee you won't change the original CPU object argument). Not having a name after the CPU& just means you're not assigning the variable to a name within the current scope (aka the brackets after the definition will ignore the argument).

When a constructor is private it usually means there's another function which will generate the Object for you. Factories will oftentimes hide an objects constructor and require some other attributes/registration before building the object for you.

Pyrce
  • 8,296
  • 3
  • 31
  • 46
  • So a private copy constructor can be used to control number of instances and prevent copying of an instance? Interesting. Thanks. – ShadoWalkeR Nov 27 '13 at 00:01
0
  1. const because you don't modify the object you are copying
  2. ampersand means reference
  3. no argument name is allowed in method declaration, because only type matters, not the name

And finally private - this code simply "hides" copy constructor from other classes, which means "don't copy me".

Iuri Covalisin
  • 645
  • 4
  • 7
0

It's a way of preventing you from (accidentally) creating a copy of an instance of your class by e.q. passing it to a function:

CPU foo;
void f1(CPU &foo) {}; f1(foo);  // work
void f2(CPU *foo) {}; f2(&foo); // work
void f3(CPU foo)  {}; f3(foo);  // fails

So you will not be able to paste it into a call by value function.

Abubadabu
  • 194
  • 1
  • 9