Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler-generated copy/assignment functions for classes with reference and const members

The book I'm reading says that when your class contains a member that's a reference or a const, using the compiler-generated copy constructor or assignment operators won't work. For instance,

#include <iostream>
#include <string>
using namespace std;

class TextBlock
{
    public:
        TextBlock (string str) : s(str) {
            cout << "Constructor is being called" << endl;
        }
        string& s;
};


int main () {
    TextBlock p("foo");
    TextBlock q(p);

    q = p;

    cout << "Q's s is " << q.s << endl;

    return(0);
}

According to my book, both the lines TextBlock q(p); and q = p; should return compiler errors. But using the g++ compiler for Linux, I'm only getting an error for the line q = p; When I comment that out, this works fine and the code compiles. The correct s is output for Q, so it's apparently being copied by the compiler-generated copy constructor. I get the same results when I change the line string& s; to const string s.

Have there been some changes to C++ that now allow the copy constructor to be generated automatically for reference and const objects, but not the assignment operator? Or maybe I'm just not understanding the book correctly? Any thoughts?

like image 293
A. Duff Avatar asked Apr 21 '14 20:04

A. Duff


2 Answers

The book is wrong. A const member or a reference member will inhibit generation of the default copy assignment operator, but doesn't prevent the compiler from generating a copy constructor.

like image 90
James Kanze Avatar answered Oct 23 '22 08:10

James Kanze


Don't try to learn a special rule here.

The compiler-generated default versions of special member functions follow a simple pattern:

  • The type-appropriate special member function is called for every subobject (base classes and members).

From that, you can work out every case.

int i;
int &ri1 = i;
int &ri2 = ri1;

is allowed, so copying an object containing an int& is allowed.

There is no assignment operator for references (ri2 = ri1; does not rebind the reference), so assignment is not allowed.

References can't be default constructed:

int& ri; // error

so a type containing int& can't be default-constructed.

An important consideration is that the access checks are done for compiler-defaulted code just as if you had written it yourself. So interesting things can happen if a base class has, for example, a private copy constructor... and you don't have to learn special rules for any of them.

like image 3
Ben Voigt Avatar answered Oct 23 '22 08:10

Ben Voigt