Size of class with virtual function adds extra 4 bytes - c++

class NoVirtual {
int a;
public:
void x() const {}
int i() const { return 1; }
};
class OneVirtual {
int a;
public:
virtual void x() const {}
int i() const { return 1; }
};
class TwoVirtuals {
int a;
public:
virtual void x() const {}
virtual int i() const { return 1; }
};
int main() {
cout << "int: " << sizeof(int) << endl;
cout << "NoVirtual: "
<< sizeof(NoVirtual) << endl;
cout << "void* : " << sizeof(void*) << endl;
cout << "OneVirtual: "
<< sizeof(OneVirtual) << endl;
cout << "TwoVirtuals: "
<< sizeof(TwoVirtuals) << endl;
return 0;
}
The output is:
NoVirtual: 4
void* : 8
OneVirtual: 16
TwoVirtuals: 16
Question is:
Since OneVirtual and TwoVirtuals class have virtual function, size of class should be sizeof(int) + sizeof(void*) i.e. 12bytes. But size is printed as 16bytes.
Can someone explain why?

I assume you are compiling on 64bit machines since size of int is 4bytes.Typically for 64bit machines pointer size will be 8 bytes and int size is 4 bytes.To satisfy Data Alignment requirement to save read cycles
compiler adds extra 4 bytes(padding) hence result is 16bytes where as actual required size is 12 bytes.

Related

reinterpret_cast memory not modified

I tried to modify an object of A indirectly by allocating 8 bytes using std::allocator. I used <int> specifically, hoping it will return aligned memory for 2 integers. Then I modified an object of A.
Why do I only see A.x=9 in the bitset (towards the end 1001), what happened to A.y=10? Do I need to align the raw pointer returned by std::allocator?
I was expecting the output below:
0000000000000000000000000000100100000000000000000000000000001010
before=0000000000000000000000000000000000000000000000000000000000000000
---------------------
sizeof(A)=8
alignof(A)=4
x: 9 y: 10
---------------------
x: 9 y: 10
after=0000000000000000000000000000000000000000000000000000000000001001
#include <bitset>
#include <iostream>
struct A {
int x;
int y;
A() = delete;
friend std::ostream &operator<<(std::ostream &os, const A &a) {
os << "x: " << a.x << " y: " << a.y;
return os;
}
};
int main(int argc, char **argv) {
std::allocator<int> alloc;
auto raw = alloc.allocate(2);
std::bitset<64> before(*raw);
before.reset();
std::cout << "before=" << before << "\n";
std::cout << "---------------------\n";
std::cout << "sizeof(A)=" << sizeof(A) << "\n";
std::cout << "alignof(A)=" << alignof(A) << "\n";
auto a = reinterpret_cast<A *>(raw);
a->x = 9;
a->y = 10;
std::cout << *a << "\n";
std::cout << "---------------------\n";
std::bitset<64> after(*raw);
std::cout << *a << "\n";
std::cout << "after=" << after << "\n";
return 0;
}
I actually don't see any undefined behviour here.
The actual problem is that you seem to assume that before(*raw) creates a bitset with a snapshot of that memory region. But that is not what happens.
See: https://en.cppreference.com/w/cpp/utility/bitset/bitset
(you call the unsigned long long constructor)
If you simply write (before after):
unsigned long long raw_converted_to_long = *raw;
You see the value is 9 - this is the reason why the bitset is filled with 9.

Joining two integers into one bigger integer in C++

I need to have two separate 16-bit integers, that can form a 32-bit integer together. But I need them to be updated whenever I change any of them. Let's say I change the value of the 32-bit, I need it to be automatically written over the two 16-bit ones and vice versa. Is this possible?
You can use a proxy class to represent your 32-bit integer:
class Proxy {
private:
uint16_t &_high, &_low;
public:
Proxy(uint16_t &high, uint16_t &low) : _high(high), _low(low) {}
Proxy &operator=(uint32_t whole) {
_high = whole >> 16;
_low = whole & 0xffff;
return *this;
}
operator uint32_t() const {
return (_high << 16) | _low;
}
};
int main() {
uint16_t high = 0xa, low = 0xb;
Proxy whole(high, low);
std::cout << std::hex;
std::cout << whole << '\n'; // a000b
high = 0xc;
low = 0xd;
std::cout << whole << '\n'; // c000d
whole = 0xe000f;
std::cout << high << ' ' << low << '\n'; // e f
return 0;
}
By providing operator uint32_t, Proxy can be implicitly converted to uint32_t in most cases.
This gets really easy with c++20 which has bit_cast. It can even be used in constexpr functions. Here are freestanding encapsulated, and really simple direct (no extra functions or classes) versions:
#include <iostream>
#include <array>
#include <cstdint>
#include <bit>
using std::uint32_t, std::uint16_t;
// Free standing functions
void place_low16(std::array<uint16_t, 2>& arr, uint16_t x) {arr[0] = x;}
void place_high16(std::array<uint16_t, 2>& arr, uint16_t x) {arr[1] = x;}
void place_32int(std::array<uint16_t, 2>& arr, uint32_t i){arr = std::bit_cast<std::array<uint16_t, 2>>(i);}
uint32_t get_ui32(const std::array<uint16_t, 2>& arr) {return std::bit_cast<uint32_t>(arr);}
// encapsulated
struct PackedInt16 {
std::array<uint16_t, 2> two_uint32s;
void place_low16(uint16_t x) {two_uint32s[0] = x;}
void place_high16(uint16_t x) { two_uint32s[1] = x; }
void place_32int(uint32_t i) { two_uint32s = std::bit_cast<std::array<uint16_t, 2>>(i); }
uint32_t get_ui32() { return std::bit_cast<uint32_t>(two_uint32s); }
};
int main()
{
// free standing functions
std::array<uint16_t, 2> packed_ints;
place_low16(packed_ints, static_cast<uint16_t>(0xffff'ffff)); //store in low int16
place_high16(packed_ints, static_cast<uint16_t>(0x1)); // store in high int16
uint32_t x = get_ui32(packed_ints); // get 32 bit uint
place_32int(packed_ints, x); // store 32 bit uint in packed int16s
std::cout << x << " " << packed_ints[0] << " " << packed_ints[1] << '\n';
// ouput: 131071 65535 1
// encapsulated
PackedInt16 packed_ints2;
packed_ints2.place_low16(static_cast<uint16_t>(0xffff'ffff));
packed_ints2.place_high16(static_cast<uint16_t>(0x1));
uint32_t x2 = packed_ints2.get_ui32();
packed_ints2.place_32int(x2);
std::cout << x2 << " " << packed_ints2.two_uint32s[0] << " " << packed_ints2.two_uint32s[1] << '\n';
// ouput: 131071 65535 1
// and now the direct approach: No functions, no classes
std::array<uint16_t, 2> packed_ints3;
packed_ints3[0] = static_cast<uint16_t>(0xffff'ffff);
packed_ints3[1] = 1;
uint32_t x3 = std::bit_cast<uint32_t>(packed_ints3);
packed_ints3 = std::bit_cast<std::array<uint16_t, 2>>(x3);
std::cout << x3 << " " << packed_ints3[0] << " " << packed_ints3[1] << '\n';
// ouput: 131071 65535 1
}
You could define a class that behaves similar to a uint16_t which works with a uint32_t value stored as reference.
In some cases there's a difference though, e.g. a conversion to uint16_t won't happen automatically in some cases.
class Uint32BitView16
{
uint32_t& m_data;
unsigned m_shift;
public:
constexpr Uint32BitView16(uint32_t& data, unsigned shift)
: m_data(data),
m_shift(shift)
{
}
constexpr operator uint16_t() const
{
return (m_data >> m_shift);
}
constexpr Uint32BitView16& operator=(uint16_t value)
{
m_data = (m_data & ~static_cast<uint32_t>(0xffff << m_shift)) | (value << m_shift);
return *this;
}
};
int main() {
uint32_t data = 0x01020304;
Uint32BitView16 v1(data, 0);
Uint32BitView16 v2(data, 16);
std::cout << std::hex;
std::cout << static_cast<uint16_t>(v1) << '\n'; // 304
std::cout << static_cast<uint16_t>(v2) << '\n'; // 102
data = 0xffff0000;
std::cout << static_cast<uint16_t>(v1) << '\n'; // 0
std::cout << static_cast<uint16_t>(v2) << '\n'; // ffff
v1 = 0xff;
std::cout << data << '\n'; // ffff00ff
}

Static Cast to CRTP Interface [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I am building up a CRTP interface and noticed some undefined behavior. So, I built up some sample code to narrow down the problem.
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a, int b, int c) : _a(a), _b(b), _c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10, 20, 30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
The output of this code is:
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
It appears that there is some problem when casting the child class, which implements the CRTP "interface", to the interface itself. This doesn't make sense to me because the class A plainly inherits from Base so, shouldn't I be able to cast an instance of A into Base?
Thanks!
You copy and slice when you cast to Base<T>.
Cast to a const Base<T>& instead:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
It turns out I was casting incorrectly to a value rather than a reference
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
should become
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;

How change class of a C++ object (implementing a variadic type)

First off: I know that it is generally a bad idea to change an object's class, but I'm implementing my own programming language, and it has variables that can contain values of any type, and even change their type at will, so please assume I'm not a beginner not understanding OO basics.
Currently, I implement my variant variables in C. Each one has a pointer to a table of function pointers, containing functions like SetAsInt(), SetAsString() etc., followed by what would be instance variables in C++. All objects are the same size.
When a variable contains a string and someone assigns an Int to it, I manually call the destructor, change the table of function pointers to point to the table used for variadic int values, and then set its int instance variable.
This is a bit hard to maintain, as every time I add a new type, I have to add a new table of function pointers and fill out all the function pointers in it. Structs of function pointers seem to be very badly type-checked, and missing fields don't lead to complaints, so I can easily accidentally forget one pointer in the list and get interesting crashes. Also, I have to repeat all the function pointers that are the same in most types.
I'd like to implement my variadic types in C++ instead, where a lot of this type-checking and inheriting default behaviours is done for me by the compiler. Is there a safe way to do this?
PS - I know I could create a wrapper object and use new to allocate a new object, but I can't have the additional extra allocation overhead for every int variable on the stack.
PPS - The code needs to be portable across Linux, Mac, iOS and Windows for now, but if someone has a standard C++ solution, that would be even better.
PPPS - The list of types is extensible, but predetermined at compile-time. The base layer of my language defines just the basic types, but the host application my language is compiled into adds a few more types.
Usage Example:
CppVariant someNum(42); // Creates it as CppVariantInt.
cout << "Original int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsInt(700); // This is just a setter call.
cout << "Changed int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsDouble(12.34); // This calls destructor on CppVariantInt and constructor on CppVariantDouble(12.34).
cout << "Converted to Double: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl; // GetAsInt() on a CppVariantDouble() rounds, or whatever.
(Imagine that beyond double and int, there would be other types in the future, like strings or booleans, but the caller of GetAsInt()/SetAsInt() shouldn't have to know what it is stored as, as long as it can be converted at runtime)
Here is a solution based on type-erasure, union and template specializations.
I'm not sure it fits your requirements.
Anyway, here is what it gets:
Anything is placed on the dynamic storage
No hierarchy required
You can easily improve it further to reduce the amount of code, but this aims to serve as a base point from which to start.
It follows a minimal, working example based on the intended use in the question:
#include<iostream>
class CppVariant {
union var {
var(): i{0} {}
int i;
double d;
};
using AsIntF = int(*)(var);
using AsDoubleF = double(*)(var);
template<typename From, typename To>
static To protoAs(var);
public:
CppVariant(int);
CppVariant(double);
int getAsInt();
double getAsDouble();
void setAsInt(int);
void setAsDouble(double);
private:
var data;
AsIntF asInt;
AsDoubleF asDouble;
};
template<>
int CppVariant::protoAs<int, int>(var data) {
return data.i;
}
template<>
int CppVariant::protoAs<double, int>(var data) {
return int(data.d);
}
template<>
double CppVariant::protoAs<int, double>(var data) {
return double(data.i);
}
template<>
double CppVariant::protoAs<double, double>(var data) {
return data.d;
}
CppVariant::CppVariant(int i)
: data{},
asInt{&protoAs<int, int>},
asDouble{&protoAs<int, double>}
{ data.i = i; }
CppVariant::CppVariant(double d)
: data{},
asInt{&protoAs<double, int>},
asDouble{&protoAs<double, double>}
{ data.d = d; }
int CppVariant::getAsInt() { return asInt(data); }
double CppVariant::getAsDouble() { return asDouble(data); }
void CppVariant::setAsInt(int i) {
data.i = i;
asInt = &protoAs<int, int>;
asDouble = &protoAs<int, double>;
}
void CppVariant::setAsDouble(double d) {
data.d = d;
asInt = &protoAs<double, int>;
asDouble = &protoAs<double, double>;
}
int main() {
CppVariant someNum(42);
std::cout << "Original int: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
someNum.setAsInt(700);
std::cout << "Changed int: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
someNum.setAsDouble(12.34);
std::cout << "Converted to Double: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
}
On a lark, I tried using placement new to do this, and I have ... something ... It compiles, it does the job, but I'm not sure if it's an improvement over pure C. Since I can't have a union of C++ objects, I create a CPPVMAX() macro to pass the largest sizeof() of all subclasses as the size to mBuf[], but that's not really pretty either.
#include <iostream>
#include <string>
#include <cmath>
#define CPPVMAX2(a,b) (((a) > (b)) ? (a) : (b))
#define CPPVMAX3(a,b,c) CPPVMAX2((a),CPPVMAX2((b),(c)))
using namespace std;
class CppVariantBase
{
public:
CppVariantBase() { cout << "CppVariantBase constructor." << endl; }
virtual ~CppVariantBase() { cout << "CppVariantBase destructor." << endl; }
virtual int GetAsInt() = 0;
virtual double GetAsDouble() = 0;
virtual void SetAsInt( int n );
virtual void SetAsDouble( double n );
};
class CppVariantInt : public CppVariantBase
{
public:
CppVariantInt( int n = 0 ) : mInt(n)
{
cout << "CppVariantInt constructor." << endl;
}
~CppVariantInt() { cout << "CppVariantInt destructor." << endl; }
virtual int GetAsInt() { return mInt; }
virtual double GetAsDouble() { return mInt; }
virtual void SetAsInt( int n ) { mInt = n; }
protected:
int mInt;
};
class CppVariantDouble : public CppVariantBase
{
public:
CppVariantDouble( double n = 0 ) : mDouble(n)
{
cout << "CppVariantDouble constructor." << endl;
}
~CppVariantDouble()
{
cout << "CppVariantDouble destructor." << endl;
}
virtual int GetAsInt()
{
if( int(mDouble) == mDouble )
return mDouble;
else
return round(mDouble);
}
virtual double GetAsDouble() { return mDouble; }
virtual void SetAsDouble( int n ) { mDouble = n; }
protected:
double mDouble;
};
class CppVariant
{
public:
CppVariant( int n = 0 ) { new (mBuf) CppVariantInt(n); }
~CppVariant() { ((CppVariantBase*)mBuf)->~CppVariantBase(); }
operator CppVariantBase* () { return (CppVariantBase*)mBuf; }
CppVariantBase* operator -> () { return (CppVariantBase*)mBuf; }
protected:
uint8_t mBuf[CPPVMAX3(sizeof(CppVariantBase),sizeof(CppVariantInt),sizeof(CppVariantDouble))];
};
void CppVariantBase::SetAsInt( int n )
{
this->~CppVariantBase();
new (this) CppVariantInt(n);
}
void CppVariantBase::SetAsDouble( double n )
{
this->~CppVariantBase();
new (this) CppVariantDouble(n);
}
int main(int argc, const char * argv[]) {
CppVariant someNum(42);
cout << "Original int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsInt(700); // This is just a setter call.
cout << "Changed int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsDouble(12.34); // This changes the class to CppVariantDouble.
cout << "Converted to Double: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
return 0;
}

where did my 4 bytes go?

#include <iostream>
#include <cstdlib>
using std::cout;
class A
{
public :
A() { cout << "A()" << this << "\n";}
~A() { cout << "~A()" << this << "\n";}
//void func() { }
virtual void debug(int a) { cout << "A::debug";}
private :
int a;
};
class A1 : public A
{
public :
A1() { cout << "A1()"<< this << "\n";}
~A1() { cout << "~A1()"<< this << "\n";}
private :
int a1;
};
class A2 : public A
{
public :
A2() { cout << "A2()"<< this << "\n";}
~A2() { cout << "~A2()"<< this << "\n";}
private :
int a2;
};
class B : public A1, public A2
{
public :
B() { cout << "B()"<< this << "\n";}
~B() { cout << "~B()"<< this << "\n";}
void debug() { cout << "B::debug()"; }
private :
int a3;
};
int main()
{
cout << "sizeof(int)" << sizeof(int) << "\n";
cout << "sizeof(void*)" << sizeof(void*) << "\n";
cout << "sizeof(A): " << sizeof(A) << "\n";
cout << "sizeof(A1): " << sizeof(A1) << "\n";
cout << "sizeof(A2): " << sizeof(A2) << "\n";
cout << "sizeof(B): " << sizeof(B) << "\n";
B b;
b.debug();
}
output :
sizeof(int)4
sizeof(void*)4
sizeof(A): 8
sizeof(A1): 12
sizeof(A2): 12
**sizeof(B): 28**
A()0x28fef4
A1()0x28fef4
**A()0x28ff00**
A2()0x28ff00
B()0x28fef4
B::debug()~B()0x28fef4
~A2()0x28ff00
~A()0x28ff00
~A1()0x28fef4
~A()0x28fef4
Both A1 and A2 are 4(vtbl) + 4(A'sint) + 4(respective int) = 12 bytes but B is 28 bytes
I know its not guaranteed but what could be the possible use of those 4 bytes...I dont see any padding issues ? Can anyone point out what am I missing ?
sizeof(A): 8
The type A has a member of type int which in your platform is 4 bytes. It also has a virtual function, which means that a vptr (virtual table pointer) is allocated for each object of your class, the size of it is another 4 bytes.
**sizeof(B): 28**
B contains one object of type A1 (12 bytes), and an object of type A2 (another 12 bytes) and it adds another int for a total of 12+12+4 = 28 bytes. This is quite straightforward.
machine word size alignment of data items within structures.
See structure packing for more information.
Multiple inheritance will produce implementation-specific memory layouts of possibly different sizes.
Virtual tables and virtual pointers for multiple virtual inheritance and type casting