Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

initialize array from constructor (should be simple) 1

Status
Not open for further replies.

apatterno

Programmer
Nov 26, 2002
368
US
Hello, this should be simple, but I'm unsure of the correct syntax for initializing an array from a constructor. Consider :

Code:
class Firable {
public:
  Firable (int wid_first, int wid_second, int wid_third)
    : wids ( {wid_first, wid_second, wid_third} )
  {
    /* ... */
  }

private:
  int wids [3];
};

I'm not sure what the right syntax is for the initializer, but the compiler doesn't seem to like this. Any ideas?
Thanks.
 
I don't think Standard C++ supports a way to do that.

GNU C++ has an extension that allows you to do so. You can check to see whether it happens to work in Visual C++, but I doubt it.
 
Hah! Thanks, as luck would have it, I happen to be using GNU C++. But that link said "Note that a constructor expression is not the same as a constructor for a C++ struct or class."

Not quite what I was looking for, but okay, oh well, I'll just do it the "wrong way" as any good programmer would say, i.e.

Code:
Firable::Firable (int wid_first, int wid_second, int wid_third)
{
  wids[0] = wid_first;
  wids[1] = wid_second;
  wids[2] = wid_third;
}

Ten bucks says it compiles exactly the same :-D

Thanks anyway!
 
Heh heh. Probably so.


But I think that link does have what you're looking for. That line is just distinguishing between constructors and constructor expressions. It doesn't mean you can't use a constructor expression in a constructor.


e.g. The following compiles and works fine for me in GCC (G++) 3.2:
Code:
class Foo
{
  public:
    Foo()
    : stuff((int []) {1, 2, 3})
    {}
  private:
    int stuff[3];
};
 
Why wrong way? It's C++ legal initialization by assignment in ctor. All constructor effects on its object called initialization (not only via ctor-initializer).
In this case we have an ordinal member initialization - no matter that's an array member. A ctor-initializer makes non-trivial work for base class or members with non-trivial constructors only.
C++ Standard:
A constructor is used to initialize objects of its class type. (12.1.2).
 
Well, it depends on what exactly is meant by "initialization."

By one definition, assignments performed in the constructor body are not initializations; the members have already been initialized to their default values at that point.

By another, more general definition, anything done in a constructor is initializing the object being constructed.

I think apatterno was referring to the more precise definition.


Assigning a value to each array member in the constructor body is "wrong" only in that it may result in the array getting initialized, then immediately changed. In that case, the program is just less efficient than it could have been.
 
Yeah, of course if the type is int[3] it doesn't really matter, because that can easily be optimized away by the compiler (without shelling out hundreds of dollars for Visual Studio, if you use GNU C++!!!)

I guess for some types with overloaded operators, initializing by assignment is not what we want, because that calls the assignment operator T::eek:perator= (const T &) instead of the copy constructor T::T (const T&) which could not be identical, in theory.

This is one of the more subtle C++ topics IMHO. It's good that we have people in the forums knowledgable about this stuff. Thanks!
 
(About terms;): let's take up The C++ Standard, 12.6.2(5)
Initializing bases and members:
5 Initialization shall proceed in the following order:
- First, ... // skipped, about virtual base classes
- Then, ... // skipped, about direct base classes
- Then, ... // skipped, about non-static data members
- Finally, the body of the constructor is executed.

 
ArkM, I think the point is that you can use intialize to refer to the intialization of the instance of the class, and you can use it to refer to the initialization of the specific data members of the class. See the paragraph of the standard above your quote:

C++ Standard 12.6.2(4) said:
If a given nonstatic data member or base class is not named by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then

— If the entity is a nonstatic data member of (possibly cv-qualified) class type (or array thereof) or a base class, and the entity class is a non-POD class, the entity is default-initialized (8.5). If the entity is a nonstatic data member of a const-qualified type, the entity class shall have a user-declared default constructor.

— Otherwise, the entity is not initialized. If the entity is of const-qualified type or reference type, or of a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of a const-qualified type, the program is ill-formed.
In other words, if the data member is not specified in the intializer list, it is either default initalized or not initialized, regardless of what happens inside the constructor body.

This is important, as you know, because "initializing" a non-POD class in the constructor body is really just assigning a new value after that member has already been truly initialized prior to the execution of the constructor.

The constructor initializes the instance of the specific class, but any code inside the its body assigns values to its particular data members.
 
uolj, the key point in the quote:
see prev post said:
... If the entity is a nonstatic data member of a const-qualified type, the entity class shall have a user-declared default constructor.
We discuss this case. See the next (last) sentence in 12.6.2(4):
C++ Standard 12.6.2(4) said:
After the call to a constructor for class X
has completed, if a member of X is neither
specified in the constructor's mem-initializers,
nor default-initialized, nor initialized during
execution of the body of constructor
,
the member has indeterminate value.
Of course, it seems as an academic chicanery...
 
Myself said:
Well, it depends on what exactly is meant by "initialization."

uolj said:
I think the point is that you can use intialize to refer to the intialization of the instance of the class, and you can use it to refer to the initialization of the specific data members of the class.


Section 8.5 talks about initialization of non-class objects.

Section 12.6 talks about initialization of class objects. This might be paraphrased as "placing the object into a valid state."


Perhaps the Standard Committee should have used different words for these two concepts. It appears to directly contradict itself. It claims that a member is not initialized if it doesn't appear in the initializer list; then it claims that members can be initialized in the constructor body.

I'd suggest that "red" initialization is meant to be the type of initialization discussed in 8.5, and that "blue" initialization is the type discussed in 12.6. That is, anything that happens in the constructor body is meant to "initialize" the object by placing it into a valid state by manipulation of its members.*

Still, this was a carelessly written section.


At any rate, you certainly can't initialize a reference or [tt]const[/tt] data member in the constructor body.
 
Well. it was a good constitutional.
Thank you.
Good luck (you and I;).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top