So what you're using is 'copy-initialization':
8.5/11 Initializers
The form of initialization (using
parentheses or =) is generally
insignificant, but does matter when
the entity being initialized has a
class type; see below. ...
The initialization that occurs in
argument passing, function return,
throwing an exception (15.1), handling
an exception (15.3), and
brace-enclosed initializer lists
(8.5.1) is called copy-initialization
and is equivalent to the form
T x = a;
The initialization that occurs in new
expressions (5.3.4), static_cast
expressions (5.2.9), functional
notation type conversions (5.2.3), and
base and member initializers (12.6.2)
is called direct-initialization and is
equivalent to the form
T x(a);
In 13.3.1.3 "Initialization by constructor", the overloads for the constructor chosen are:
When objects of class type are direct-initialized (8.5), or copy-initialized from an expression of the same or a derived class type (8.5), overload resolution selects the constructor. For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized. For copy initialization, the candidate functions are all the converting constructors (12.3.1) of that class.
So, for copy-initialization, the copy constructor must be available. However, the compiler is permitted to 'optimize away' the copy:
12.2/1 Temporary objects
Even when the creation of the temporary object is avoided (12.8), all the semantic restrictions must be respected as if the temporary object was created. [Example: even if the copy constructor is not called, all the semantic restrictions, such as accessibility (clause 11), shall be satisfied. ]
You can get the effect you want by avoiding copy-initialization and using direct-initialization:
const A &b(B());
Note:
Since newer versions of GCC apparently have a different behavior, I thought I'd post this note, which might address the difference (with both behaviors still standards conforming):
8.5.3/5 References says:
If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):
The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within
that object.
A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.
The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.
I originally read the last sentence ("the constructor that would be used...") to apply to both options, but maybe it should be read as only applying to the seconds option - or at least maybe that's how the GCC maintainers are reading it.
I'm not sure if this is what's going on between the differing behavior of GCC versions (comments welcome). We're definitely reaching the limits of my language-lawyering skills...