2

I've always been taught that

1. Class c(arg);

and

2. Class c = arg;

are two totally equivalent statements, but look at this situation.

#include <iostream>

class Intermediary {
};

class Left {
  public:
    Left(const Intermediary &) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }   
};

class Right {
  public:
    // The argument is there just so that the example can work, see below
    Right(int) { 
        std::cout << __PRETTY_FUNCTION__  << std::endl;
    }

    operator Intermediary () const {
        std::cout << __PRETTY_FUNCTION__  << std::endl;

        return Intermediary();    
    }
};

Now if I do this:

Left l = Right(0);

The compiler will complain

error: conversion from Right to non-scalar type Left requested

But if I do this:

Left l(Right(0)); 

Then everything compiles and the output is

Right::Right(int)
Right::operator Intermediary() const
Left::Left(const Intermediary&)

However, if I do this:

Left l = (Intermediary)Right(0);

then everything compiles again and the output is just like the one above.

So obviously

1. Class c(arg);

and

2. Class c = arg;

are not the same, but why not, and what's the difference? I couldn't find anything about this online.

4

1 回答 1

5

I've always been taught that Class c(arg); and Class c = arg; are two totally equivalent statements, but look at this situation.

It turns out they are not equivalent. The first one constructs the Class c out of an arg, while the second one constructs a Class out of an arg and then copy-constructs Class c out of it. Note that the implementation is allowed to ellide that copy, and it usually does.

Left l = Right(0);

This requires a conversion from Right to Intermediary, and one from Intermediary to Left. This two sequential user defined conversions are not allowed by the standard, you have to do at least one of them explicit as you do with:

Left l = (Intermediary)Right(0);
于 2011-10-29T00:51:38.680 回答