11
const QPointF points[] =
{
    QPointF(r.left() - i, r.top() - i),
    QPointF(r.right() + i, r.top() - i),
    QPointF(r.right() + i, r.bottom() + i),
    QPointF(r.left() - i, r.bottom() + i),
    points[0] // is this line valid (according to the C++ standard)?
};

While this compiles with the MS Visual Studio Compiler, i am not sure if this is valid code according to the C++ Standard.

Quotes from the Standard would be highly appreciated.

smerlin
  • 6,446
  • 3
  • 35
  • 58
  • `g++ -pedantic` doesn't complain. – kennytm Nov 06 '10 at 19:36
  • 1
    ... although it doesn't complain about `const int x = x;` either. – kennytm Nov 06 '10 at 19:43
  • I would think that it's correct(points[0] refers to a valid object by that time), but I wouldn't know for sure. The grammar checks out, obviously, and flipping through Stroustroup just says "An array can be initialized by a list of values. points[0] is a value, so it seems correct. – rtpg Nov 06 '10 at 19:49
  • @Dasuraga: No, `points[0]` does _not_ refer to a valid object "by that time". `points[0]` has an **indeterminate** value. – Lightness Races in Orbit Sep 11 '11 at 16:21

4 Answers4

4

C++03/C++11 answer


No, it's not.

On the right-hand side of the =, points does exist1 but the initialiser is only applied after all its operands have been evaluated.

  • If points is at namespace scope (and thus has static storage duration and has been zero-initialized2), then this is "safe" but your use of points[0] there is going to give you 0, rather than QPointF(r.left() - i, r.top() - i) again.

  • If points has automatic storage duration — it has not yet been initialised so your use of points[0] is attempting to use an uninitialised variable, where points[0] has an indeterminate value... which is bad3.

It's difficult to provide standard references for this, other than to say that there is nothing in 8.5 "Initializers" that explicitly makes this possible, and rules elsewhere fill in the rest.


1 [n3290: 3.3.2/1]: The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [ Example:

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

Here the second x is initialized with its own (indeterminate) value. —end example ]

2 [n3290: 3.6.2/2]: Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place. [..]

3 [n3290: 17.6.3.3/2]: [..] [ Note: Operations involving indeterminate values may cause undefined behavior. —end note ]

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • I didn't realize it was a valid alternative spelling :) – EvilTeach Sep 11 '11 at 14:15
  • @EvilTeach: "Initialiser" is the correct English spelling. The "alternative" with a "z" is found in an offshoot of English, known as "American English". I believe there a few people in parts of the continent of North America who adhere to this modified lexicon. – Lightness Races in Orbit Sep 11 '11 at 18:01
2

from http://www.comeaucomputing.com/pcgi-bin/compiler.cgi:

Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 8: warning: variable "points" is used before its value is set
      points[0] // is this line valid (according to the C++ standard)?
Anycorn
  • 50,217
  • 42
  • 167
  • 261
0

Since there is no sequence point in the statement, the result is undefined, much like for the i=i++ example quoted at that wikipedia page.

Otherwise said, nothing specifies, whether the compiler should first evaluate everything, then assign, or do evaluate-assign for each element separately and in which order.

eudoxos
  • 18,545
  • 10
  • 61
  • 110
  • Hmm, I don't know why I didn't think of that. Potentially a much simpler way to describe the scenario. – Lightness Races in Orbit Sep 11 '11 at 18:10
  • At least the order in which the initializers for each element are evaluated is specified. – smerlin Sep 12 '11 at 09:38
  • @smerlin: why do you think so? The comma in `{.., ..}` is not the "comma operator" in this context. (Similar to the wikipedia article referenced, sub pt. 4: "Note that a function call f(a,b,c) is not a use of the comma operator and the order of evaluation for a, b, and c is unspecified.") – eudoxos Sep 12 '11 at 09:55
  • 1
    @eudoxos: While the quote of the standard in my answer does not cover the OPs question, it covers this - and it says that the order is specified. – smerlin Sep 12 '11 at 18:32
-2

Old Answer (misses the point):

I checked the current C++0x draft, and there i found the sentence 8.5.1.17 which says:

17 The full-expressions in an initializer-clause are evaluated in the order in which they appear.

So while this sentence is not part of the C++ Standard from 2003, im quite sure that this should be working in any up to date compiler, if this is part of C++0x.

Edit:
The comments made me rethink this matter. This line only ensures that the QPointF objects are created in the order in which they occur in the array initialization (relevant if the element constructors have observable side-effects). The problem is, the value of points is indeterminate during its array initialization. So there cant be a guarantee for a valid value of points[0] either, at least not if you rely on the standard.

smerlin
  • 6,446
  • 3
  • 35
  • 58