views:

138

answers:

3

I have following two classes:

template <size_t size>
class Cont{
 public:
 char charArray[size];
};
template <size_t size>
class ArrayToUse{
 public:
 Cont<size> container;
 inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){}
};

I have three following lines of code at global scope:

const Cont<12> container={"hello world"};
ArrayToUse<11> temp(container);
char (&charArray)[11]=temp.container.charArray;

In totality of my code The only usage of "container" object is for initialization of an object of "ArrayToUse" class as mentioned and after initialization of "charArray" reference to "temp.container.charArray" I'll use that reference in rest of my code, now I'm wondering does compiler reserve memory for "container" object since that's got a temporary usage?

A: 

it totaly depends on your particular compiler so i'd say inspect the assembly and find out! the compiler could optimize container out, or it could neglect to do so.

flownt
+2  A: 

Any variable defined at global scope has memory reserved for it at compile time. That does not mean it's guaranteed to be properly initialized, but it's there all the same.

At link-time, Visual C++ offers the option to strip unused data and functions via /OPT - see here.

Steve Townsend
@flownt - it compiles OK for me
Steve Townsend
yes on closer inspection it's okay but the syntax looks quite arcane. in any case the reference is not to container but to the subobject in arraytouse so container may still be optimized out.
flownt
@Steve Townsend_I'm not referencing "container" object using charArray, I'm referencing "temp.container.charArray".
Pooria
@flownt - the compiler cannot optimize this out. That was the question, if you want to discuss link-time optimization that's a different matter.
Steve Townsend
@Steve Townsend_So what've you got to tell about link-time optimization ?
Pooria
@Poonia - edited in what I know
Steve Townsend
how are link-time optimizations not optimizations for you? would you think that any compiler reïnstantiates the virtual-table for every translation unit? no they are all colapsed to one at link-time.
flownt
@flownt - what have vtables got to do with this question? This is about global variables.
Steve Townsend
@Steve - well about vtables 1)they're global, 2) its a link-time optimisation. otoh i made gcc generate code at O3 with lto and I even added static to the first line so it knew this could be the only place where it's used and it still refused to optimise it away, i'd therefore assume compilers are not (yet) smart enough to compile that thing away òr the standard just doesn't allow such a thing(maybe the standard finds it observable..)
flownt
@flownt_So I'd assume this would only happen as a link-time optimization as Steve Townsend has mentioned.
Pooria
A: 

The compiler should create the container variable in the compiled object file. The linker is the one that can tell if it's needed or not (for an exported symbol, or from another compilation unit if declared extern).

But...

The type Cont<x> is unrelated to Cont<x+1>. You cannot depend on the memory of a member variable being layed out in similar fashions. Heck, you cannot even know if it looks the same, since there is this thing called 'template specialization':

// your code
template <size_t size>
class Cont{
 public:
 char charArray[size];
};

// my evil tweak
// I'm the worst compiler ever but I feel that this
// array would better be represented as a map...
template<> class Cont<12> {
   std::map<int,char> charArray;
};

// your screwed up result
Cont<12> c12;
Cont<11>& c11( reinterpret_cast<Cont<11>&>(c12) );
char (&s11)[11] = c11.charArray; // points to the first byte of a list object...

EDIT -- @UncleBen's comment insinuates I'm overdoing here. And he's right.

according to wikipedia,

  • A pointer to a POD-struct object, suitably converted using a reinterpret cast, points to its initial member and vice versa, implying that there is no padding at the beginning of a POD-struct.

So in this case,

  • where the charArray is the first member of a Cont<n>, and there are no non-POD members

  • there is no assignment operator, nor a destructor

It is safe.

xtofl
Unless there is a specialization, does the compiler really have any say in how the class will be laid out in memory (the offset of first member is 0 and the array is contiguous)?
UncleBens
@UncleBens: good question - I'll search around on alignment, packing etc...
xtofl