string initialize

N

Neo

Hi All,
When I use following syntax

class obj1 = obj2;

This means I am using copy ctor. Now for string

if I use
string str = "ABCD";

will this create a temporary object and then call copy constructor of
str variable?

- Vikram S
 
O

olekk

Neo said:
Hi All,
When I use following syntax

class obj1 = obj2;

This means I am using copy ctor. Now for string

if I use
string str = "ABCD";

will this create a temporary object and then call copy constructor of
str variable?

- Vikram S

It will
 
S

SG


GNU C++ won't.

The standard allows a compiler to elide copies in some cases. The GNU C
++ compiler will generate code that constructs ONLY ONE string object
for 'str' in this case. So, no copy ctor is invoked. This behaviour is
not guaranteed by the C++ standard, though. Another compiler might
create a temporary string object which is then used as source for copy-
constructing 'str' and destroyed after that.

To make sure that no temporary string object is created you could use
string str ("ABCD");
instead. This is an explicit, direct initialization.


Cheers!
SG
 
R

Rolf Magnus

SG said:
GNU C++ won't.

The standard allows a compiler to elide copies in some cases. The GNU C
++ compiler will generate code that constructs ONLY ONE string object
for 'str' in this case. So, no copy ctor is invoked.

However, the compiler will still require it, even if not used.
 
P

Peter Remmers

SG said:
GNU C++ won't.

The standard allows a compiler to elide copies in some cases. The GNU C
++ compiler will generate code that constructs ONLY ONE string object
for 'str' in this case. So, no copy ctor is invoked. This behaviour is
not guaranteed by the C++ standard, though. Another compiler might
create a temporary string object which is then used as source for copy-
constructing 'str' and destroyed after that.

To make sure that no temporary string object is created you could use
string str ("ABCD");
instead. This is an explicit, direct initialization.

I always thought that

type var = initial;

is the same as

type var(initial);

And the difference is only syntactic sugar, plus the latter may have
ambiguitiy problems as it looks like a function declaration.

The former calls a constructor of "type" that receives a parameter of
"initial"'s type, as does the latter. Provided a constructor with a
matching parameter type exists for "type".

Everything else would make no sense, as the former syntax is clearly
construction with initialization (i.e. the same as the latter), and
different from

type var;
var = initial;

which is default construction followed by assignment.


For the OP's examples,

The copy constructor, no doubt. The compiler-generated one, if not defined.

The constructor that takes a "const char *", if provided. And it must be
provided. Even if the compiler wanted to first construct a temporary and
use that to to copy construct str, the temporary itself couldn't be
constructed without a constructor that takes a "const char *". I see no
reason why a compiler would ever choose to go the way of the temporary.
> string str ("ABCD");

The same applies to the explicit constructor call syntax. The compiler
could also generate a temporary here to convert from "const char *" to
"string", but it most likely does not.

Even if the language specs allow use of a temporary (I don't know), what
sense would it make?
 
A

Andrey Tarasevich

Peter said:
I always thought that

type var = initial;
Copy-initialization.

is the same as

type var(initial);

Direct-initialization.

No, they are not the same. They are _almost_ the same in only one case -
when 'initial' has the same type as 'var'. Otherwise, these are not even
remotely the same (at least conceptually, in general case).

Even when the types are the same, declaring the copy-constructor as
'explicit' will break the former variant.
And the difference is only syntactic sugar, plus the latter may have
ambiguitiy problems as it looks like a function declaration.

The latter (as well as the former) can have other problems, including
ambiguity problems.
The former calls a constructor of "type" that receives a parameter of
"initial"'s type,
as does the latter. Provided a constructor with a
matching parameter type exists for "type".

That's incorrect. A counterexample that illustrates the difference is
rather easy to produce

struct S { operator int() const; };
struct D { D(int); };

S s;
D d1(s); // OK
D d2 = s; // ERROR

In this case the the 'd1' is initialized with a constructor that
receives a completely different type (not 'S'). And the initialization
of 'd2' does not compile at all.
Everything else would make no sense, as the former syntax is clearly
construction with initialization (i.e. the same as the latter),

Quite the opposite. The syntax is clearly different, which provides the
opportunity to assign a different semantics to that syntax, which is
what was done in this case.
For the OP's examples,


The copy constructor, no doubt. The compiler-generated one, if not defined.

No. There's no way to tell what's happening in this case without knowing
the type of 'obj2'. Even if 'obj2' has the same type as 'obj1', it still
doesn't mean that the copy constructor is used.

A counterexample is easy to produce

struct D {
explicit D(const D&);
D(int);
operator int() const;
};

D d1(0);
D d2 = d1;

The copy-constructor is not used in this case.
The constructor that takes a "const char *", if provided. And it must be
provided.

Correct, it must be provided for the purpose of creating the
aforementioned temporary.
Even if the compiler wanted to first construct a temporary and
use that to to copy construct str, the temporary itself couldn't be
constructed without a constructor that takes a "const char *".

Precisely. But this is only because the RHS is a string literal, not an
object of class type. If the RHS was a class, there would be an
alternative path for creating the temporary - the conversion operator

struct D {};
struct S { operator D() const; };

S s;
D d = s;

In this case class 'D' doesn't have a conversion constructor from 'S',
yet the code is well-formed.
I see no
reason why a compiler would ever choose to go the way of the temporary.

The reason is the requirement of the C++ language specification. The
compiler is required is use this approach as the "baseline" and then it
is allowed to "optimize away" the temporary. Nevertheless, the
well-formed-ness of the code is verifies as if the temporary is created
in any case.
The same applies to the explicit constructor call syntax. The compiler
could also generate a temporary here to convert from "const char *" to
"string",

Incorrect. Target class has a constructor that accepts 'const char*',
which immediately means that it is explicitly prohibited from generating
an intermediate temporary of 'string' type by the language specification.
but it most likely does not.

In simply "does not". No "most likely" is involved here.
Even if the language specs allow use of a temporary (I don't know), what
sense would it make?

The "sense" in this case is not the temporary itself, but a specific
construction sequence (or "path") in case of copy-initialization, which
is required to involve the copy-constructor (at least conceptually). A
temporary is just a [undesired] side-effect of that specific
construction paths, which is why the language specification explicitly
allows it to be "optimized away".

Once again, to illustrate the difference between these construction
paths, I already provided you with one example (here it is again)

struct D { D(int); };
struct S {
operator int() const;
};

S s;
D d1(s); // OK
D d2 = s; // ERROR

But once we make the following modification, we get an opposite effect

struct D { D(int); };
struct S {
operator int() const;
operator D() const; // <- added
};

S s;
D d1(s); // ERROR
D d2 = s; // OK

Consider these two examples carefully and they will help you to
understand the difference between direct-initialization and
copy-initialization.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,161
Messages
2,570,891
Members
47,423
Latest member
henerygril

Latest Threads

Top