Aman Deep Gautam
Aman Deep Gautam

Reputation: 8777

C++: why code is compiling

I do not understand how this code is compiling. Can somebody please explain what is going on in there.

#include <iostream>

using namespace std;

class B
{
public:    
    B(const char* str = "\0") //default constructor
    {
        cout << "Constructor called" << endl;
    }    

    B(const B &b)  //copy constructor
    {
        cout << "Copy constructor called" << endl;
    } 
};

int main()
{ 
    B ob = "copy me";    //why no compilation error.
    return 0;
}

The optput is: Constructor called

P.S.: I could not think of a more apt title than this, Anyone who can think of a better title, please modify it.

Upvotes: 0

Views: 283

Answers (7)

Analog File
Analog File

Reputation: 5316

Edit: after discussion with Kerrek SB I got a copy of the C++11 standard. I was wrong, there's a temporary. I'm editing this reply to reflect my newly acquired understanding.

15 years ago I knew C++ extremely well (that was around the time the first standard was to be released). I haven't used it since late 1998 so I have forgotten a lot and I know almost nothing of the recent standards.

The code is correct.

 B ob = "copy me";    //why no compilation error.

There's no error. This is parsed as a declaration of an initialized variable. B is the type, ob the name of the variable, "copy me" the initializer.

The initializer is of type const char* and there is, in class B, a constructor that takes a const char* typed single argument. That constructor is not declared restricted by explicit and therefore can be used in this context.

Either a temporary object is created and then copied (you see both lines printed out) or the copy is elided and only the conversion constructor is called to construct directly at the destination (you see only one line printed). The standard explicitly allows this even if the copy constructor has side effects.

The program execution will print Constructor called to stdout. It may or may not then also print Copy constructor called. There is no error.

Upvotes: -1

New Moon
New Moon

Reputation: 817

This is because of implicit conversion. Add a Explicit to your Default constructor and try. it will Fail to compile.

Upvotes: 0

tu_ru
tu_ru

Reputation: 267

If you add keyword explicit to your default constructor to prevent implicit conversion. Then it will not compile. Your answer is implicit conversion.

Upvotes: 7

Vikdor
Vikdor

Reputation: 24134

That's because of implicit conversion of the assignment statement to

B ob("copy me");

Try this to fail compilation (look at the explicit keyword):

#include <iostream>

using namespace std;

class B
{
public:    
    explicit B(const char* str = "\0") //default constructor
    {
        cout << "Constructor called" << endl;
    }    

    B(const B &b)  //copy constructor
    {
        cout << "Copy constructor called" << endl;
    } 
};

int main()
{ 
    B ob = "copy me";    //why no compilation error.
    return 0;
}

Upvotes: 4

Kiril Kirov
Kiril Kirov

Reputation: 38173

Because this

B ob = "copy me";

invokes the copy constructor, which takes argument const B &b and you class B has a constructor

B(const char* str = "\0")

which is not defined as explicit.

The compiler is allowed to make one implicit conversion.


So, what happens here:

B ob = "copy me";

is:

  1. Create a temp, unnamed object B, using the provided const char* str - this is allowed, since class B has constructor, which takes one argument and is not defined as explicit. In other words, all objects with type B can be constructed from a const char*
  2. Create the object ob, using the temp object, created in 1..

Upvotes: 7

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726987

[it shouldn't compile because] the specified line does not match in data types

There is no compilation error because there exists a constructor of B that takes const char* as an argument, allowing for conversion between const char* and B.

Upvotes: 3

Kerrek SB
Kerrek SB

Reputation: 477514

The type of "copy me" is char const[8], which decays to char const *. Since the default constructor is not explicit, "copy me" can be implicitly converted to B, and thus ob can be copy-constructed from that implicitly converted, temporary B-object.

Had the default constructor been declared explicit, you would have had to write one of the following:

B ob1 = B("copy me");
B ob2("copy me");

Had the copy constructor also been declared explicit, you would have had to say one of these:

B ob3(B("copy me"));
B ob4("copy me");

In practice, all copies will be elided by any half-decent compiler, and you always end up with a single default constructor invocation.

Upvotes: 10

Related Questions