Initializing array member objects in c++

Started by
35 comments, last by Fruny 19 years, 10 months ago
Hello, I have somewhat of a problem and no idea how this is done or even if it's possible. But this is what I have:

class Plane3
{
   public:
      inline
         Plane3(const Point3 &p0, 
                const Point3 &p1,
                const Point3 &p2);
      ...

   private:
      Point3 mP[3];
};
  
What I want to do is initialize the mP array member in the constructor. Something like this:

inline 
   Plane3:: Plane3(const Point3 &p0,
                  const Point3 &p1,
                  const Point3 &p2)
      : mP[0](p0), mP[1](p1), mP[2](p2)
   {
   }
  
Of course this isn't valid code so my question is what syntax can you use when initializing array member objects when constructing an object? Having three separate member variables and initializing them isn't acceptable, I need it to be an array. Thanks! *edit* Damn smilies. [edited by - asp_ on June 10, 2004 5:51:47 AM]
Advertisement
there are special tags you can use on this forum that format code properly.

Anyway you can''t program like that.

Understand that:

Point3 mP[3];

... is just declaring a pointer to an array, not the array itself.

you have to actually create the array with a new Point3[3] to allocate the memory actually used for the array. and importantly in the destructor using delete [] mP; rather then just delete mp;

I can see you are trying to be smart and do it in the initaliser list, which is admirable but also wrong - because at that stage the memory hasn''t been allocated for the array yet.

so first
mp = new Point3[3];

to allocate the memory.

then you just do

mp[0] = p0;
...
...


Also be warey of optimising before you know there is a bottleneck. Get it done, if there''s a bottleneck you can find it and deal with it later.
inline is subjective to the compiler anyway - unless you specifically force it to inline it may disregard that. It may also inline stuff you haven''t asked it too... and it will do that itself if it knows there will be a speed increase.

Careful with mixing references and consts and things like that too. Do you really want to be sending over a reference to an object rather then a pointer to it? There is a difference when it comes to assignment.

Using a reference and setting a reference like that will invoke a copy contructor or overloaded assignment constructor, and create a new copy of the object in the array.

Using a pointer would just copy over the pointer... but then you have to decide who gets control of the lifetime of Point3... so that it gets disposed of properly.
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
paulsdsrubbish,
Thanks for the reply. I think you assumed I knew less C++ than I do since my question was syntactical =) However it is imperative that the default constructors are avoided. Thanks for the suggestions though. Maybe I''m misstaken in my replies, if so, please correct me =)

quote:
there are special tags you can use on this forum that format code properly.

And they were used =) Maybe I should have used the source tags instead of the code ones but I used them for readability.

quote:
Point3 mP[3];

... is just declaring a pointer to an array, not the array itself.

Actually that seems wrong to me. The default constructors are run thus the array is fully declared. I think the standard guarantees that each member variable be available and available in the order declared, once the constructor body is run. Pointers would not cause the constructors to be executed.

quote:
I can see you are trying to be smart and do it in the initaliser list, which is admirable but also wrong

Well most code I see initializer lists are used extensively in order to avoid the extra call to the default constructor. Then again most code I see may be wrong.

quote:
so first
mp = new Point3[3];

No thanks. I don''t want it on the heap. Nor do I want the default constructors to run. more correct would be:
mP = new Point3[] = { Point3(...), Point3(...), Point3(...) };
But that still leaves the heap issue. Since I''m using objects required by the processor to be 16-byte aligned, allocating on the heap is somewhat expensive not to mention it should generally be avoided in code used as often as my primitives are.

quote:
Also be warey of optimising before you know there is a bottleneck. Get it done, if there''s a bottleneck you can find it and deal with it later.

The problem is these are base objects and are getting constructed/destroyed all the time. Of course if the default constructor is empty the call will be optimised away.

I''m starting to believe there is no way to do what I want unless I use a std::vector for my array but that''s out of the question. The only way to solve this seems to be to separate the array member mP into 3 variables mP0, mP1, mP2. This is exactly what I wanted to avoid. Anyone who knows the best way to solve the issue? Hopefully I''m not being a total moron =)
That was me up there. Sorry
quote:Original post by paulsdsrubbish
Understand that:

Point3 mP[3];

... is just declaring a pointer to an array, not the array itself.

Er, no, it''s a statically allocated array. What are you talking about?

quote:you have to actually create the array with a new Point3[3] to allocate the memory actually used for the array. and importantly in the destructor using delete [] mP; rather then just delete mp;

This would be true if it were a dynamically allocated array (Point3*), which it isn''t.
asp_, you may consider creating an ambiguous union inside your class to remedy the problem. Here, let me whip up what I mean.

class Plane3{   public:      inline Plane3( const Point3 &p0, const Point3 &p1, const Point3 &p2 );   private:      union      {          Point3 m_rgPoints[ 3 ];          struct          {             Point3 m_P0, m_P1, m_P2;          };      };};inline Plane3::Plane3( const Point3 &p0, const Point3 &p1, const Point3 &p2 ): m_P0( p0 ), m_P1( p1 ), m_P2( p2 ) { }


This way you can have an array 'interface' to your Point3 data and still be able to initialize the data in the constructor.

[edited by - MikeMJH on June 10, 2004 4:11:00 PM]
MikeMJH,
That was beautiful. But unfortunatley it bails with error C2621 which says:

member 'identifier' of union 'union' has copy constructor
A union member cannot have a copy constructor.

So that would kind of kill the purpose of the entire thing since I HAVE to have a copy constructor. I'm using MS Visual C++ 7.1 btw, just in case it's another annoying standard non-compliance thing.

*edit*
Added MSVC version.

[edited by - asp_ on June 10, 2004 4:27:05 PM]
quote:Original post by asp_
MikeMJH,
That was beautiful. But unfortunatley it bails with error C2621 which says:

member 'identifier' of union 'union' has copy constructor
A union member cannot have a copy constructor.

So that would kind of kill the purpose of the entire thing since I HAVE to have a copy constructor. I'm using MS Visual C++ 7.1 btw, just in case it's another annoying standard non-compliance thing.

*edit*
Added MSVC version.

[edited by - asp_ on June 10, 2004 4:27:05 PM]


Let me just write up a quick test and see if GCC gives me a similar error.

Yeah, I do. So looks like that solution is out. :-/

[edited by - MikeMJH on June 10, 2004 4:57:33 PM]
why does it have to be an array?

from the looks of things you''re hardcoding the size of the array so just split it into three Point3 objects and initialise them in the initialiser list.

if you really need array access you could declare an array of 3 pointers to Point3 objects and access them through that for loops, whatever.

You basically have the following options (there are probably more, but it''s early):
1) leave the code as it is and pay for the default constructor
2) make an array of heap objects
3) use a vector of objects
4) see above

BTW don''t listen to paulsdsrubbish, I think he thinks you''re using java or something!!

"That''s not a bug, it''s a feature!"
--me
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
ChaosEngine,
quote:
why does it have to be an array?

It doesn''t HAVE to be. I could have three member variables but that would prevent me from accessing it like an array. Of course I could assume that they will be thighly packed and just take the pointer of the first member variable and use that as the base address of the array but that doesn''t feel like solid coding.

quote:
from the looks of things you''re hardcoding the size of the array so just split it into three Point3 objects and initialise them in the initialiser list.

No.

quote:
if you really need array access you could declare an array of 3 pointers to Point3 objects and access them through that for loops, whatever.

Pointers = needs to be allocated with new which is too slow for what I want. Using loops when accessing the elements would definitely kill my performance and I see no reason why I''d need to do that even with pointers.

quote:
You basically have the following options (there are probably more, but it''s early):
1) leave the code as it is and pay for the default constructor
2) make an array of heap objects
3) use a vector of objects
4) see above

1) Yeah that is an option and is what I''m currently using. But I have several classes like this and even though it''s not THAT costly, it''s not free either.
2) Not an option. Would be slower than option 1.
3) Even slower than option 2.
4) Error: C4717

I''m going to be using option 1 until Stroustrup appears in a vision and tells me what the true path is. Thanks for the replies

This topic is closed to new replies.

Advertisement