By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,949 Members | 1,511 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,949 IT Pros & Developers. It's quick & easy.

initialization problem

P: n/a
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}

This code is the consequence of lazy Search/Replace (s/msg0/msg/g -
initially the function parameter and the first variable after the _=_
was msg0).
But shouldn't the compiler complain about the initialization of an
object use the same object? What am I missing?

TIA,

Marcelo Pinto

Dec 20 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a

Marcelo Pinto wrote:
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}
But shouldn't the compiler complain about the initialization of an

object use the same object? What am I missing?


Which compiler? The above code (after removing all extra portion) gives
redeclaration error with Comeau online (msg has already been declared
in the current scope)

Dec 20 '05 #2

P: n/a
Marcelo Pinto wrote:
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}

This code is the consequence of lazy Search/Replace (s/msg0/msg/g -
initially the function parameter and the first variable after the _=_
was msg0).
But shouldn't the compiler complain about the initialization of an
object use the same object? What am I missing?


you are allowed to redeclare already visible identifiers in different
scopes. only redefining an identifier that has already been defined in
the same scope is illegal and yields a compiler error.

your for() loop body is a new scope, thus the identifier msg can be
defined again. you have to be aware though that you are effectively
hiding the already visible identifier, which is probably not what you
intended to do.

-- peter

Dec 20 '05 #3

P: n/a
Neelesh Bodas wrote:
Marcelo Pinto wrote:
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}

But shouldn't the compiler complain about the initialization of an


object use the same object? What am I missing?

Which compiler? The above code (after removing all extra portion) gives
redeclaration error with Comeau online (msg has already been declared
in the current scope)


Really? Did you remove the 'for' as well? It's introduces the proper
scope limitation for the "inner" msg...

V
Dec 20 '05 #4

P: n/a
Neelesh Bodas wrote:
Marcelo Pinto wrote:
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}
But shouldn't the compiler complain about the initialization of an

object use the same object? What am I missing?


Which compiler? The above code (after removing all extra portion) gives
redeclaration error with Comeau online (msg has already been declared
in the current scope)


you probably removed a little bit too much of the given example... ;-)

-- peter

Dec 20 '05 #5

P: n/a
Marcelo Pinto wrote:
void f(const std::string & msg)
{ { std::string msg = msg + " " + another_string; //1 } }
.... But shouldn't the compiler complain about the initialization of an
object use the same object? What am I missing?


The Standard clearly states, that in

int x = 12;
{ int x = x; }

the second _x_ is initialized with its own (indeterminate) value.

But in this particular case I wonder what will happen, since _msg_
should probably be constructed before it is used. My belief is that
_msg_ will be constructed with the default constructor, then the
expression will be evaluated and then the assignment operator will be
called.

Martin.
Dec 20 '05 #6

P: n/a

"Marcelo Pinto" <mp******@gmail.com> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
This is legal. This msg local to the for loop hides the msg parameter. So
it basically becomes:
std::string msg = "" + " " + another_string;

which is probably why you're asking.

No, there are generally no compiler warnings for hiding variables. Although
there generally are for hiding methods in classes.
//...
}
//...
}

This code is the consequence of lazy Search/Replace (s/msg0/msg/g -
initially the function parameter and the first variable after the _=_
was msg0).
But shouldn't the compiler complain about the initialization of an
object use the same object? What am I missing?

TIA,

Marcelo Pinto

Dec 20 '05 #7

P: n/a

Neelesh Bodas escreveu:
Which compiler? The above code (after removing all extra portion) gives
redeclaration error with Comeau online (msg has already been declared
in the current scope)


aCC: HP ANSI C++ B3910B A.03.37

Dec 20 '05 #8

P: n/a
Neelesh Bodas wrote:
Marcelo Pinto wrote:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1
//...
}
//...
}

Which compiler? The above code (after removing all extra portion) gives
redeclaration error with Comeau online (msg has already been declared
in the current scope)


It can hardly be redeclared as long as it is in the inner scope. You
probably removed the "extra" for loop. Don't do that or at least remove
only `for (...)` line.

Martin.
Dec 20 '05 #9

P: n/a
Jim Langston wrote:
"Marcelo Pinto" <mp******@gmail.com> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
Hi,

Consider the following code snipet:
void f(const std::string & msg)
{
//...
for (...)
{
//...
std::string msg = msg + " " + another_string; //1


This is legal. This msg local to the for loop hides the msg parameter. So
it basically becomes:
std::string msg = "" + " " + another_string;

which is probably why you're asking.

No, there are generally no compiler warnings for hiding variables. Although
there generally are for hiding methods in classes.


The local "msg" variable is accessed before it has been initialized
(because it is used in its own initializer.) Since the value of the msg
variable is indeterminate before its initialization, the outome of this
expression, though legal, is undefined.

Greg

Dec 20 '05 #10

P: n/a

Victor Bazarov wrote:
Really? Did you remove the 'for' as well? It's introduces the proper
scope limitation for the "inner" msg...


Yeah ;-) I removed everything which caused trouble for compilation :-)

-N

Dec 21 '05 #11

P: n/a

"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Jim Langston wrote:
"Marcelo Pinto" <mp******@gmail.com> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
> Hi,
>
> Consider the following code snipet:
>
>
> void f(const std::string & msg)
> {
> //...
> for (...)
> {
> //...
> std::string msg = msg + " " + another_string; //1


This is legal. This msg local to the for loop hides the msg parameter.
So
it basically becomes:
std::string msg = "" + " " + another_string;

which is probably why you're asking.

No, there are generally no compiler warnings for hiding variables.
Although
there generally are for hiding methods in classes.


The local "msg" variable is accessed before it has been initialized
(because it is used in its own initializer.) Since the value of the msg
variable is indeterminate before its initialization, the outome of this
expression, though legal, is undefined.

Greg


Actually, I was reading somewhere that
std::string msg("Hello");
is more effecient than
std::string msg = "Hello";

Because one uses the regular constructor, one uses the assignment
constructor.

If the assignment constructor is uses, isn't the default constructor called
first? Or am I mistaken on that?
Dec 21 '05 #12

P: n/a

Jim Langston wrote:
"Greg" <gr****@pacbell.net> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Jim Langston wrote:
"Marcelo Pinto" <mp******@gmail.com> wrote in message
news:11*********************@g44g2000cwa.googlegro ups.com...
> Hi,
>
> Consider the following code snipet:
>
>
> void f(const std::string & msg)
> {
> //...
> for (...)
> {
> //...
> std::string msg = msg + " " + another_string; //1

This is legal. This msg local to the for loop hides the msg parameter.
So
it basically becomes:
std::string msg = "" + " " + another_string;

which is probably why you're asking.

No, there are generally no compiler warnings for hiding variables.
Although
there generally are for hiding methods in classes.


The local "msg" variable is accessed before it has been initialized
(because it is used in its own initializer.) Since the value of the msg
variable is indeterminate before its initialization, the outome of this
expression, though legal, is undefined.

Greg


Actually, I was reading somewhere that
std::string msg("Hello");
is more effecient than
std::string msg = "Hello";

Because one uses the regular constructor, one uses the assignment
constructor.

If the assignment constructor is uses, isn't the default constructor called
first? Or am I mistaken on that?


No, an object's constructor is not called before an object is
initialized with itself. For example, compiling and running this
program:

#include <string>

int main()
{
std::string s = s + "hello";
}

terminates with a segmentation fault on my machine. It crashes because
the program is accessing s's storage as if it were a constructed
std::string. Although the Standard does not require that any warning be
issued, gcc does have a special switch, -Winit-self, to check for this
kind of mistake (though I can't imagine it is all that common). But it
is not entirely straightforward, since enabling the warning requires
that two other switches also be set.

Actually these declarations:

std::string msg("Hello");
std::string msg = "Hello";

are equivalent. Both call the same constructor. The use of the "=" in
one is confusing since it looks very much like last line in this
sequence:

std::string msg;

msg = "Hello";

In this case, there is a call to the std::string's assignment operator
because msg has already been constructed. In general, the rule-of-thumb
is to prefer construction over assignment (as in a loop for example)
since construction is usually more efficient. I'm not sure whether that
is the case with std::string, though I can't think of any reason why it
would not be.

Greg

Dec 21 '05 #13

P: n/a

Greg escreveu:
The local "msg" variable is accessed before it has been initialized
(because it is used in its own initializer.) Since the value of the msg
variable is indeterminate before its initialization, the outome of this
expression, though legal, is undefined.

Greg


That is precisely how I interpreted it. But in that case shouldn't the
compiler have warned? Is this valid C++ (acording to the Standard)? Is
it UB?

TIA,

Marcelo Pinto

Dec 21 '05 #14

P: n/a

Greg wrote:
Actually these declarations:

std::string msg("Hello");
std::string msg = "Hello";

are equivalent. Both call the same constructor. The use of the "=" in
one is confusing since it looks very much like last line in this
sequence:


in this case because the constructor of std::string from const char *
is implicit (and the general rule that does not allow 2 implicit
conversions does not apply converting char[6] to const char*).

But if a class were declared with an explicit constructor the second
version should fail to compile.

This however should also be equivalent:

std::string msg = std::string("Hello");

and will not call operator= nor invoke a copy-constructor even without
RVO.
(Try it on a class that has copy-construction and assignment disabled
and an explicit constructor).

Dec 21 '05 #15

P: n/a
"Jim Langston" <ta*******@rocketmail.com> writes:
Actually, I was reading somewhere that
std::string msg("Hello");
is more effecient than
std::string msg = "Hello";

Because one uses the regular constructor, one uses the assignment
constructor.
What is "the assignment constructor"?

Constructors are "special member functions" that construct objects.
A constructor that doesn't take any arguments is usually called
default constructor, and one that takes a reference to another
object of the same type is called copy constructor.

Assignment is usually spelled operator =, and is something else.
If the assignment constructor is uses, isn't the default constructor called
first? Or am I mistaken on that?


#include <string>

using std::string;

int main()
{
std::string msg1("Hello"); // 1
std::string msg2 = "Hello"; // 2
return 0;
}

In theory line 1 calls uses a constructor taking a char* argument,
and line 2 first constructs an anonymous temporary object using
the same constructor as line 1, and then uses the copy constructor
to create msg2. In practice the two lines are equivalent, since
the creation of the temporary is optimized away. (For classes
where the copy constructor is private or protected line 2 doesn't
compile though).

/Niklas Norrthon

Dec 21 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.