surprised that this is valid...

W

werasm

Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;
};

I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense? I was surprised when I discovered this.

Regards,

Werner
 
J

jason.cipriani

Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;

};


It's a consequence of when the scope of a variable starts. Similarly,
the following also compiles by itself:

void function () {
int x(x);
int y = y;
}

Some compilers will warn you about the value of 'x' and 'y' being used
initialized (you are trying to initialize it with it's own value but
it has not been initialized yet), but it is legal. It's just kind of
meaningless.

See the entire section [3.3] in the standard. A variable comes into
scope at it's point of declaration, which, according to [3.3.1/1]:

"The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any)..."

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
int x(x); // now it uses x from above
int y = y; // same here
}

Similarly, if you have a parameter to your constructor named y_, then
it uses that one instead:

struct x {
x (int y_) : y_(y_) { }
int y_;
};

In that case it initializes the member y_ to the value of the y_
parameter passed to the constructor.
I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense?

I can't think of any time where it would make sense. It's more just a
strange consequence of scoping rules.
I was surprised when I discovered this.

It makes more sense why it is legal after reading the above rules.
Regards,

Werner


Jason
 
P

Paavo Helde

Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;
};

I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense? I was surprised when I discovered this.

By memory from an old thread in c.l.c++.m:

class TreeNode {
public:
TreeNode(TreeNode& parent): parent_(parent) {}
bool IsRoot() const {return this==&parent_;}
private:
TreeNode& parent_;
};

struct x
{
x(): root_( root_ ){}

TreeNode root_;
};

regards
Paavo
 
J

Jeff Schwab

Paavo said:
By memory from an old thread in c.l.c++.m:

class TreeNode {
public:
TreeNode(TreeNode& parent): parent_(parent) {}
bool IsRoot() const {return this==&parent_;}
private:
TreeNode& parent_;
};

struct x
{
x(): root_( root_ ){}

TreeNode root_;
};

I can't decide whether that's brilliant or horrid. It certainly merits
a multi-line comment. (Thanks for the food for thought, regardless.)
 
J

jason.cipriani

Jeff Schwab said:
I can't decide whether that's brilliant or horrid. It certainly merits a
multi-line comment. (Thanks for the food for thought, regardless.)

It does have a certain morbidly fascinating car-accident quality to
it...
 
P

Paul Brettschneider

Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;

};


It's a consequence of when the scope of a variable starts. Similarly,
the following also compiles by itself:

void function () {
int x(x);
int y = y;
}

Some compilers will warn you about the value of 'x' and 'y' being used
initialized (you are trying to initialize it with it's own value but
it has not been initialized yet), but it is legal. It's just kind of
meaningless.

See the entire section [3.3] in the standard. A variable comes into
scope at it's point of declaration, which, according to [3.3.1/1]:

"The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any)..."

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
int x(x); // now it uses x from above
int y = y; // same here
}

Similarly, if you have a parameter to your constructor named y_, then
it uses that one instead:

struct x {
x (int y_) : y_(y_) { }
int y_;
};

In that case it initializes the member y_ to the value of the y_
parameter passed to the constructor.
I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense?

I can't think of any time where it would make sense. It's more just a
strange consequence of scoping rules.

"int x = x;" is used in macro form to shut up bogus uninitialised variable
warnings without generating useless assembler instructions. Apparently some
people have harsh code size constraints...
 
J

Jeff Schwab

Paul said:
Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;

};

It's a consequence of when the scope of a variable starts. Similarly,
the following also compiles by itself:

void function () {
int x(x);
int y = y;
}

Some compilers will warn you about the value of 'x' and 'y' being used
initialized (you are trying to initialize it with it's own value but
it has not been initialized yet), but it is legal. It's just kind of
meaningless.

See the entire section [3.3] in the standard. A variable comes into
scope at it's point of declaration, which, according to [3.3.1/1]:

"The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any)..."

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
int x(x); // now it uses x from above
int y = y; // same here
}

Similarly, if you have a parameter to your constructor named y_, then
it uses that one instead:

struct x {
x (int y_) : y_(y_) { }
int y_;
};

In that case it initializes the member y_ to the value of the y_
parameter passed to the constructor.
I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense?
I can't think of any time where it would make sense. It's more just a
strange consequence of scoping rules.

"int x = x;" is used in macro form to shut up bogus uninitialised variable
warnings without generating useless assembler instructions. Apparently some
people have harsh code size constraints...

From my treasure chest:

/* Use this no-op function template to avoid compiler warnings about
* unused variables. Optimized machine code (as generated by g++
* -O) will completely elide calls of the form unused(some_object).
*/
template<typename T>
void unused(T const&) {
/* Do nothing. */
}

As a hack, you can instead cast the variable to void:

(void)some_object;
// or
static_cast<void>(some_object);
 
G

Greg Herlihy

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
  int x(x); // now it uses x from above
  int y = y; // same here

}

No, both x and y are still being initialized with their own
indeterminate values - the x and y declarations in the outer scope
make no difference here. In short, the inner x and y declarations hide
the outer ones.

There is one notable exception, however:

const int i = 2;
{
int i;
}

In this case, the inner "i" declares an array of two ints.

Greg
 
P

Paul Brettschneider

Jeff said:
Paul said:
Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;

};

It's a consequence of when the scope of a variable starts. Similarly,
the following also compiles by itself:

void function () {
int x(x);
int y = y;
}

Some compilers will warn you about the value of 'x' and 'y' being used
initialized (you are trying to initialize it with it's own value but
it has not been initialized yet), but it is legal. It's just kind of
meaningless.

See the entire section [3.3] in the standard. A variable comes into
scope at it's point of declaration, which, according to [3.3.1/1]:

"The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any)..."

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
int x(x); // now it uses x from above
int y = y; // same here
}

Similarly, if you have a parameter to your constructor named y_, then
it uses that one instead:

struct x {
x (int y_) : y_(y_) { }
int y_;
};

In that case it initializes the member y_ to the value of the y_
parameter passed to the constructor.

I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense?
I can't think of any time where it would make sense. It's more just a
strange consequence of scoping rules.

"int x = x;" is used in macro form to shut up bogus uninitialised
variable warnings without generating useless assembler instructions.
Apparently some people have harsh code size constraints...

From my treasure chest:

/* Use this no-op function template to avoid compiler warnings about
* unused variables. Optimized machine code (as generated by g++
* -O) will completely elide calls of the form unused(some_object).
*/
template<typename T>
void unused(T const&) {
/* Do nothing. */
}

Oh, I like it and it's definitely more portable than the current annotation
system until it is standardised. But note that I said unitialised, not
unused.
 
J

jason.cipriani

No, both x and y are still being initialized with their own
indeterminate values - the x and y declarations in the outer scope
make no difference here. In short, the inner x and y declarations hide
the outer ones.

Oops, thanks for catching that, Greg.
There is one notable exception, however:

const int i = 2;
{
int i;
}

In this case, the inner "i" declares an array of two ints.

Greg
 
J

Jeff Schwab

Paul said:
Jeff said:
Paul said:
(e-mail address removed) wrote:

Hi all,

I've per chance noticed that this code compiles without warnings:

struct x
{
x(): y_( y_ ){}

int y_;

};
It's a consequence of when the scope of a variable starts. Similarly,
the following also compiles by itself:

void function () {
int x(x);
int y = y;
}

Some compilers will warn you about the value of 'x' and 'y' being used
initialized (you are trying to initialize it with it's own value but
it has not been initialized yet), but it is legal. It's just kind of
meaningless.

See the entire section [3.3] in the standard. A variable comes into
scope at it's point of declaration, which, according to [3.3.1/1]:

"The point of declaration for a name is immediately after its complete
declarator (clause 8) and before its
initializer (if any)..."

Note that if there is an x or a y (or in your case a y_) in a larger
scope, then it will use the larger scoped one instead:

int x = 0, y = 0;

void function () {
int x(x); // now it uses x from above
int y = y; // same here
}

Similarly, if you have a parameter to your constructor named y_, then
it uses that one instead:

struct x {
x (int y_) : y_(y_) { }
int y_;
};

In that case it initializes the member y_ to the value of the y_
parameter passed to the constructor.

I've used gcc 4.1.0, comeau online and all compilers available at
dinkumware online.

Are there cases where similar code (a member initialising itself with
itself) would make sense?
I can't think of any time where it would make sense. It's more just a
strange consequence of scoping rules.
"int x = x;" is used in macro form to shut up bogus uninitialised
variable warnings without generating useless assembler instructions.
Apparently some people have harsh code size constraints...
From my treasure chest:

/* Use this no-op function template to avoid compiler warnings about
* unused variables. Optimized machine code (as generated by g++
* -O) will completely elide calls of the form unused(some_object).
*/
template<typename T>
void unused(T const&) {
/* Do nothing. */
}

Oh, I like it and it's definitely more portable than the current annotation
system until it is standardised. But note that I said unitialised, not
unused.

Whoops. :-/

I've never seen "int x = x", but I have seen and used "int x = int()",
or more often "T t = t()".
 

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

Similar Threads


Members online

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,498
Latest member
log5Sshell/alfa5

Latest Threads

Top