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?
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.
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.
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.
Related
A very simple thought that got me wondering: is there anything to be gained from using the following in a class:
static const int maximum_hp{10};
Rather than
int maximum_hp() const{return 10;};
...?
As far as I can see, the first way makes it easier to override the value of maximum_hp if needed in child classes (by declaring it virtual, of course); static data members cannot be modified, however. For constant primitive types, it seems, to me, to be a better way to go about it.
There is one thing which the static member gives you that the function does not: if the value is present in the class definition like you've shown, it can be used as a constant expression (such as an array bound or a template argument). In other words, this is legal:
std::array<int, Class::maximum_hp_static_memer> a;
while this is not:
std::array<int, c.maximum_hp_function()> a;
I am trying to create a template class that contains a pointer to an arbitrary class instance and function as follows:
template<class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
FunctPtr functPtr_;
C* instPtr_;
public:
A(FunctPtr functPtr, C* instPtr)
: functPtr_(functPtr)
, instPtr_(instPtr) {}
};
However, I want to be able to create instances of this class without dynamic memory allocation using placement new. Does the C++ standard guarantee this template class is of fixed size for all classes C?
In Don Clugston's article on pointers I noticed a chart of the various sizes for member functions pointers on various compilers and a few compilers aren't always the same size. I thought I was hosed but is this standards compliant? From the C++ standard sec. 5.2.10 on Reinterpret cast:
— converting a prvalue of type “pointer to member function” to a different pointer to member function
type and back to its original type yields the original pointer to member value.
Would that statement from the C++ standard indicate member function pointers are all of the same size?
If not I suppose I could still rewrite the code as follows to take advantage of that reinterpret_cast guarantee explicitly:
class GenericClass;
template<class C>
class A {
typedef void (GenericClass::*GenFunctPtr)();
typedef void (C::*SpecificFunctPtr)();
GenFunctPtr functPtr_; //store any kind of function ptr in this fixed format
GenericClass* instPtr_;
public:
A(SpecificFunctPtr functPtr, C* instPtr)
: functPtr_(reinterpret_cast<GenFunctPtr>(functPtr))
, instPtr_(reinterpret_cast<GenericClass*>(instPtr)) {}
void DoSomething()
{
//now convert pointers back to the original type to use...
reinterpret_cast<SpecificFunctPtr>(functPtr_);
reinterpret_cast<C*>(instPtr_);
}
};
This now would seem to be required to be all the same size and yet be standards compliant, right? I'd prefer the first option however if I must the 2nd will also work. Thoughts?
I don't know if the implementation details of pointer-to-member are specified in the standard (can't find it), but since we know that C* will have the same size for all C, we can just determine the size of FunctPtr for various types C and just add a static_assert:
template <class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
static_assert(sizeof(FunctPtr) == 16,
"unexpected FunctPtr size"); // from coliru, clang and gcc
FunctPtr functPtr_;
C* instPtr_;
...
};
At least I tried this with several types of classes ({base, derived, multiple derived} x {virtual, non-virtual}) and it always gave the same size.
This is probably platform and/or compiler specific, as Pointers to member functions are very strange animals indicates:
The size of a pointer-to-member-function of a class that uses only single inheritance is just the size of a pointer.
The size of a pointer-to-member-function of a class that uses multiple inheritance is the size of a pointer plus the size of a size_t.
which is not what I see in clang or gcc.
Microsoft compilers use different sizes of member pointers depending on how complex the class is. Technically this isn't compliant (since you can define pointers to members even when the class definition isn't visible), but it works sufficiently well in practice that they do it by default. Pragmas and compiler switches are available to control this behaviour. See for example https://msdn.microsoft.com/en-us/library/83cch5a6.aspx.
Even so the pointers for any given class are always the same size, it's just different classes may have different sized pointers to members.
Is this legal in c++11? Compiles with the latest intel compiler and appears to work, but I just get that feeling that it is a fluke.
class cbase
{
virtual void call();
};
template<typename T> class functor : public cbase
{
public:
functor(T* obj, void (T::*pfunc)())
: _obj(obj), _pfunc(pfunc) {}
virtual void call()
{
(_obj)(*_pfunc)();
}
private:
T& _obj;
void (T::*_pfunc)();
//edited: this is no good:
//const static int size = sizeof(_obj) + sizeof(_pfunc);
};
class signal
{
public:
template<typename T> void connect(T& obj, void (T::*pfunc)())
{
_ptr = new (space) functor<T>(obj, pfunc);
}
private:
cbase* _ptr;
class _generic_object {};
typename aligned_storage<sizeof(functor<_generic_object>),
alignment_of<functor<_generic_object>>::value>::type space;
//edited: this is no good:
//void* space[(c1<_generic_object>::size / sizeof(void*))];
};
Specifically I'm wondering if void* space[(c1<_generic_object>::size / sizeof(void*))]; is really going to give the correct size for c1's member objects (_obj and _pfunc). (It isn't).
EDIT:
So after some more research it would seem that the following would be (more?) correct:
typename aligned_storage<sizeof(c1<_generic_object>),
alignment_of<c1<_generic_object>>::value>::type space;
However upon inspecting the generated assembly, using placement new with this space seems to inhibit the compiler from optimizing away the call to 'new' (which seemed to happen while using just regular '_ptr = new c1;'
EDIT2: Changed the code to make intentions a little clearer.
const static int size = sizeof(_obj) + sizeof(_pfunc); will give the sum of the sizes of the members, but that may not be the same as the size of the class containing those members. The compiler is free to insert padding between members or after the last member. As such, adding together the sizes of the members approximates the smallest that object could possibly be, but doesn't necessarily give the size of an object with those members.
In fact, the size of an object can vary depending not only on the types of its members, but also on their order. For example:
struct A {
int a;
char b;
};
vs:
struct B {
char b;
int a;
};
In many cases, A will be smaller than B. In A, there will typically be no padding between a and b, but in B, there will often be some padding (e.g., with a 4-byte int, there will often be 3 bytes of padding between b and a).
As such, your space may not contain enough...space to hold the object you're trying to create there in init.
I think you just got lucky; Jerry's answer points out that there may be padding issues. What I think you have is a non-virtual class (i.e., no vtable), with essentially two pointers (under the hood).
That aside, the arithmetic: (c1<_generic_object>::size / sizeof(void*)) is flawed because it will truncate if size is not a multiple of sizeof(void *). You would need something like:
((c1<_generic_object>::size + sizeof(void *) - 1) / sizeof(void *))
This code does not even get to padding issues, because it has a few of more immediate ones.
Template class c1 is defined to contain a member T &_obj of reference type. Applying sizeof to _obj in scope of c1 will evaluate to the size of T, not to the size of reference member itself. It is not possible to obtain the physical size of a reference in C++ (at least directly). Meanwhile, any actual object of type c1<T> will physically contain a reference to T, which is typically implemented in such cases as a pointer "under the hood".
For this reason it is completely unclear to me why the value of c1<_generic_object>::size is used as a measure of memory required for in-pace construction of an actual object of type c1<T> (for any T). It just doesn't make any sense. These sizes are not related at all.
By pure luck the size of an empty class _generic_object might evaluate to the same (or greater) value as the size of a physical implementation of a reference member. In that case the code will allocate a sufficient amount of memory. One might even claim that the sizeof(_generic_object) == sizeof(void *) equality will "usually" hold in practice. But that would be just a completely arbitrary coincidence with no meaningful basis whatsoever.
This even looks like red herring deliberately inserted into the code for the purpose of pure obfuscation.
P.S. In GCC sizeof of an empty class actually evaluates to 1, not to any "aligned" size. Which means that the above technique is guaranteed to initialize c1<_generic_object>::size with a value that is too small. More specifically, in 32 bit GCC the value of c1<_generic_object>::size will be 9, while the actual size of any c1<some_type_t> will be 12 bytes.
Say I have some data allocated somewhere in my program, like:
some_type a;
and I want to wrap this data in a class for access. Is it valid to say,
class Foo {
private:
some_type _val;
public:
inline void doSomething() { c_doSomething(&_val); }
}
Foo *x = reinterpret_cast<Foo *>(&a);
x->double();
The class has no virtual functions, and only includes a single data item of the type I'm trying to wrap. Does the C++ standard specify that this reinterpret_cast is safe and valid? sizeof(Foo) == sizeof(some_type), no address alignment issues, or anything? (In my case, I'd be ensuring that some_type is either a primitive type like int, or a POD structure, but I'm curious what happens if we don't enforce that restriction, too - for example, a derived class of a UIWidget like a UIMenuItem, or something.)
Thanks!
Is it valid to say...
No, this is not valid. There are only a small number of types that a can be treated as; the complete list can be found in an answer I gave to another question.
Does the C++ standard specify that this reinterpret_cast is safe and valid?
The C++ Standards says very little about reinterpret_cast. Its behavior is almost entirely implementation-defined, so use of it is usually non-portable.
The correct way to do this would be to either
have a Foo constructor that takes a some_type argument and makes a copy of it or stores a reference or pointer to it, or
implement your "wrapper" interface as a set of non-member functions that take a some_type object by reference as an argument.
14882/1998/9.2.17:
"A pointer to a PODstruct
object, suitably converted using a reinterpret_cast, points to its initial
member (or if that member is a bitfield,
then to the unit in which it resides) and vice versa. [Note: There
might therefore be unnamed padding within a PODstruct
object, but not at its beginning, as necessary to
achieve appropriate alignment. ]"
So, it would be valid if your wrapper was strictly a POD in itself. However, access specifiers mean that it is not a strictly a POD. That said, I would be interested in knowing whether any current implementation changes object layout due to access specifiers. I think that for all practical purposes, you are good to go.
And for the case when the element is not a POD, it follows that the container is not a POD, and hence all bets are off.
Since your Foo object is already only valid as long as the existing a is valid:
struct Foo {
some_type &base;
Foo(some_type &base) : base (base) {}
void doSomething() { c_doSomething(&base); }
}
//...
Foo x = a;
x.doSomething();
You want to look up the rules governing POD (plain old data) types. If the C++ class is a POD type, then yes, you can cast it.
The details of what actually happens and how aliasing is handled are implementation defined, but are usually reasonable and should match what would happen with a similar C type or struct.
I happen to use this a lot in a project of mine that implements B+ trees in shared memory maps. It has worked in GCC across multiple types of Linux and BSDs including Mac OS X. It also works fine in Windows with MSVC.
Yes, this is valid as long as the wrapper type you are creating (Foo in your example) is a POD-type.
If you want to associate some constant value with a class, here are two ways to accomplish the same goal:
class Foo
{
public:
static const size_t Life = 42;
};
class Bar
{
public:
enum {Life = 42};
};
Syntactically and semantically they appear to be identical from the client's point of view:
size_t fooLife = Foo::Life;
size_t barLife = Bar::Life;
Is there any reason other than just pure style concerns why one would be preferable to another?
The enum hack used to be necessary because many compilers didn't support in-place initialization of the value. Since this is no longer an issue, go for the other option. Modern compilers are also capable of optimizing this constant so that no storage space is required for it.
The only reason for not using the static const variant is if you want to forbid taking the address of the value: you can't take an address of an enum value while you can take the address of a constant (and this would prompt the compiler to reserve space for the value after all, but only if its address is really taken).
Additionally, the taking of the address will yield a link-time error unless the constant is explicitly defined as well. Notice that it can still be initialized at the site of declaration:
struct foo {
static int const bar = 42; // Declaration, initialization.
};
int const foo::bar; // Definition.
They're not identical:
size_t *pLife1 = &Foo::Life;
size_t *pLife2 = &Bar::Life;
One difference is that the enum defines a type that can be used as a method parameter, for example, to get better type checking. Both are treated as compile time constants by the compiler, so they should generate identical code.
static const values are treated as r-values just like enum in 99% of code you'll see. Constant r-values never have memory generated for them. The advantage enum constants is they can't become l-values in that other 1%. The static const values are type safe and allow for floats, c-strings, etc.
The compiler will make Foo::Life an l-value if it has memory associated with it. The usual way to do that is to take its address. e.g. &Foo::Life;
Here is a subtle example where GCC will use the address:
int foo = rand()? Foo::Life: Foo::Everthing;
The compiler generated code uses the addresses of Life and Everything. Worse, this only produces a linker error about the missing addresses for Foo::Life and Foo::Everything. This behavior is completely standard conforming, though obviously undesirable. There are other compiler specific ways that this can happen, and all standard conforming.
Once you have a conforming c++11 compiler the correct code will be
class Foo {
public:
constexpr size_t Life = 42;
};
This is guaranteed to always be an l-value and it's type-safe, the best of both worlds.
Well, if needed, you can take the address of a static const Member Value. You've have to declare a separate member variable of enum type to take the address of it.
Another third solution?
One subtle difference is that the enum must be defined in the header, and visible for all. When you are avoiding dependencies, this is a pain. For example, in a PImpl, adding an enum is somewhat counter-productive:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
enum { Life = 42 } ;
private :
MyImpl * myImpl ;
}
Another third solution would be a variation on the "const static" alternative proposed in the question: Declaring the variable in the header, but defining it in the source:
// MyPImpl.hpp
class MyImpl ;
class MyPimpl
{
public :
static const int Life ;
private :
MyImpl * myImpl ;
}
.
// MyPImpl.cpp
const int MyPImpl::Life = 42 ;
Note that the value of MyPImpl::Life is hidden from the user of MyPImpl (who includes MyPImpl.hpp).
This will enable the MyPimpl author to change the value of "Life" as needed, without needing the MyPImpl user to recompile, as is the overall aim of the PImpl.