Custom deallocator with an std::vector doesn't get called - c++

I am expecting this code to print "Hello world" - "Hello " when the memory is deallocated and "world" in main. However "Hello" never gets printed, meaning that my deallocator doesn't get called. What's the proper way to implement it?
#include <iostream>
#include <vector>
class MyAllocator : public std::allocator<uint8_t>
{
public:
void deallocate(uint8_t* data, std::size_t size)
{
std::cout << "Hello ";
std::allocator<uint8_t>::deallocate(data, size);
}
};
int main()
{
{
std::vector<uint8_t, MyAllocator> v(100);
}
std::cout << "world\n";
return 0;
}
I assume it just calls the default std::allocator<uint8_t>::deallocate() function, but I am not seeing a way to prevent it and make it call my function.

In fact your allocator will work if you define rebind:
#include <iostream>
#include <vector>
class MyAllocator : public std::allocator<uint8_t>
{
public:
template <typename U>
struct rebind
{
typedef MyAllocator other;
};
void deallocate(uint8_t* data, std::size_t size)
{
std::cout << "Hello ";
std::allocator<uint8_t>::deallocate(data, size);
}
};
int main()
{
{
std::vector<uint8_t, MyAllocator> v(100);
}
std::cout << "world\n";
return 0;
}
Produces:
Hello world

std::allocator defines the member template rebind<U>.
And std::vector properly uses it to make sure it allocates the right chunks of memory, with the appropriate size and alignment, so even though you passed your custom allocator, the rebinding results in actually using the standard allocator.
See for example http://en.cppreference.com/w/cpp/concept/Allocator for the potential members of an allocator.

Related

How to create unique_ptr with static deleter

I would like to have a member function unique-ptr with a static deleter function where the function is known at compiletime and no function pointer is required at allocation. I do not know if it is possible but this test confuses me:
#include <memory>
#include <string>
#include <iostream>
struct Apa {
std::string name;
~Apa() {
std::cout << name << " deleted\n";
}
};
static void staticDeleter(Apa *a) {
std::cout << "static deleter\n";
delete a;
}
int main() {
auto deleter = [] (Apa *a) {
std::cout << "deleter\n";
delete a;
};
{
// This is what I want but as a member of a struct
auto ptr1 = std::unique_ptr<Apa, decltype(deleter)>{new Apa{"Apan"}}; // <----------------
std::cout << sizeof(ptr1) << " -> Apan\n";
}
{
auto ptr2 = std::unique_ptr<Apa, decltype(&staticDeleter)>(new Apa{"Beata"}, staticDeleter);
// When trying to omit this argument this line does not compile ------------^
std::cout << sizeof(ptr2) << " -> Beta\n";
}
}
This results in the output
8 -> Apan
deleter
Apan deleted
16 -> Beta
static deleter
Beata deleted
So unless there is some unknown compiler magic, the size of the pointers indicate that it is in fact possible to create a unique ptr with static deleter function.
When trying to do the same thing inside a struct
#include <memory>
#include <iostream>
struct Apa{
};
struct Container {
using deleter = decltype((Apa*) {}); // Edit: This was a typo: se below
std::unique_ptr<Apa, deleter> ptr ;
};
int main() {
std::cout << sizeof(Container::ptr) << "\n";
}
The output 16 shows that the unique_ptr does want a pointer to the deleter function.
Is there any way to make this work so that I define a unique_ptr with a custom deleter function inside a class that is statically defined instead of specified at runtime?
Edit:
After some feedback from #eerorika i realized that the code actually works if the lambda is written correctly. Working code:
#include <memory>
#include <iostream>
struct Apa{
~Apa() {
std::cout << "Apa deleted\n";
}
};
struct Container {
using deleter = decltype([](Apa* apa) {
std::cout << "deleter\n";
delete apa;
});
std::unique_ptr<Apa, deleter> ptr = std::unique_ptr<Apa, deleter>{new Apa} ;
};
int main() {
std::cout << sizeof(Container::ptr) << "\n";
Container container{};
}
Yields output:
8
deleter
Apa deleted
using deleter = decltype((Apa*) {});
This is an unnecessarily convoluted way of writing:
using deleter = Apa*;
The type Apa* doesn't satisfy the requirement that std::unique_ptr imposes on its deleter because Apa* isn't a FunctionObject. The example program is ill-formed (at least if you try to create an instance of it). Hence, it doesn't matter what size the object is.
Is there any way to make this work so that I define a unique_ptr with a custom deleter function inside a class that is statically defined instead of specified at runtime?
Your lambda example works since C++20. You can define similar deleter as a class, which works with earlier versions as well. For example:
struct deleter {
void operator()(Apa* ptr) {
std::cout << "custom deleter\n";
delete ptr;
}
};
struct Container {
std::unique_ptr<Apa, deleter> ptr ;
};

How to write a constructor for non-named class [duplicate]

Is there a way to declare a constructor or a destructor in an unnamed class? Consider the following
void f()
{
struct {
// some implementation
} inst1, inst2;
// f implementation - usage of instances
}
Follow up question : The instances are ofcourse constructed (and destroyed) as any stack based object. What gets called? Is it a mangled name automatically assigned by the compiler?
The simplest solution is to put a named struct instance as a member in the unnamed one, and put all of the functionality into the named instance. This is probably the only way that is compatible with C++98.
#include <iostream>
#include <cmath>
int main() {
struct {
struct S {
double a;
int b;
S() : a(sqrt(4)), b(42) { std::cout << "constructed" << std::endl; }
~S() { std::cout << "destructed" << std::endl; }
} s;
} instance1, instance2;
std::cout << "body" << std::endl;
}
Everything that follows requires C++11 value initialization support.
To avoid the nesting, the solution for the construction is easy. You should be using C++11 value initialization for all members. You can initialize them with the result of a lambda call, so you can really execute arbitrarily complex code during the initialization.
#include <iostream>
#include <cmath>
int main() {
struct {
double a { sqrt(4) };
int b { []{
std::cout << "constructed" << std::endl;
return 42; }()
};
} instance1, instance2;
}
You can of course shove all the "constructor" code to a separate member:
int b { [this]{ constructor(); return 42; }() };
void constructor() {
std::cout << "constructed" << std::endl;
}
This still doesn't read all that cleanly, and conflates the initialization of b with other things. You could move the constructor call to a helper class, at the cost of the empty class still taking up a bit of space within the unnamed struct (usually one byte if it's the last member).
#include <iostream>
#include <cmath>
struct Construct {
template <typename T> Construct(T* instance) {
instance->constructor();
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
Construct c { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
} instance1, instance2;
}
Since the instance of c will use some room, we might as well get explicit about it, and get rid of the helper. The below smells of a C++11 idiom, but is a bit verbose due to the return statement.
struct {
double a { sqrt(4) };
int b { 42 };
char constructor { [this]{
std::cout << "constructed" << std::endl;
return char(0);
}() };
}
To get the destructor, you need the helper to store both the pointer to an instance of the wrapped class, and a function pointer to a function that calls the destructor on the instance. Since we only have access to the unnamed struct's type in the helper's constructor, it's there that we have to generate the code that calls the destructor.
#include <iostream>
#include <cmath>
struct ConstructDestruct {
void * m_instance;
void (*m_destructor)(void*);
template <typename T> ConstructDestruct(T* instance) :
m_instance(instance),
m_destructor(+[](void* obj){ static_cast<T*>(obj)->destructor(); })
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(m_instance);
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
void destructor() {
std::cout << "destructed" << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Now you're certainly complaining about the redundancy of the data stored in the ConstructDestruct instance. The location where the instance is stored is at a fixed offset from the head of the unnamed struct. You can obtain such offset and wrap it in a type (see here). Thus we can get rid of the instance pointer in the ConstructorDestructor:
#include <iostream>
#include <cmath>
#include <cstddef>
template <std::ptrdiff_t> struct MInt {};
struct ConstructDestruct {
void (*m_destructor)(ConstructDestruct*);
template <typename T, std::ptrdiff_t offset>
ConstructDestruct(T* instance, MInt<offset>) :
m_destructor(+[](ConstructDestruct* self){
reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(self) - offset)->destructor();
})
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(this);
}
};
#define offset_to(member)\
(MInt<offsetof(std::remove_reference<decltype(*this)>::type, member)>())
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this, offset_to(cd) };
void constructor() {
std::cout << "constructed " << std::hex << (void*)this << std::endl;
}
void destructor() {
std::cout << "destructed " << std::hex << (void*)this << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Unfortunately, it doesn't seem possible to get rid of the function pointer from within ConstructDestruct. This isn't that bad, though, since its size needs to be non-zero. Whatever is stored immediately after the unnamed struct is likely to be aligned to a multiple of a function pointer size anyway, so there may be no overhead from the sizeof(ConstructDestruct) being larger than 1.
You can not declare a constructor or destructor for an unnamed class because the constructor and destructor names need to match the class name. In your example, the unnamed class is local. It has no linkage so neither mangled name is created.
If you are thinking of C++ names, then any class that has objects has to have a destructor whether you create it explicitly or not. So yes, the compiler knows how to assign a name. Whether that naming convention is any of your business, however, probably not.
Actually, you can create a structure or also a namespace without a name. You still need to have names somewhere because at the time you link all of that, the linker needs some kind of a name to make it all work, although in many cases it will be local names that are resolved immediately at compile time--by the assembler.
One way to know of the names assigned by the compiler is to look at the debug strings and see what corresponds to the different addresses that you're interested in. When you compile with -g then you should get all the necessary debug for your debugger to place your current at the right place with the right "names"... (I've see the namespaces without a name it says " namespace", I'm pretty sure structures use the same trick at a higher level.)

How can I have an object with differing parameter types while it's also in a vector?

I currently wish to have a vector of objects where each object has differing properties.
Intended outcome:
//v is a vector
v.push_back(ttSaveObj(5, "int example"));
v.push_back(ttSaveObj("Hello, world!", "string example"));
std::cout << v[0].data << " " << v[0].variableName << std::endl; //Intended Output: 5 int example
std::cout << v[1].data << " " << v[1].variableName << std::endl; //Intended Output: Hello, world! string example
Based on this answer I tried having a constructor function for the class with <void*> in the template, but this seems just create a pointer to void (as I partially expected).
ttSaveObj.hpp:
template <typename T>
class ttSaveObj {
public:
ttSaveObj(T pVar, std::string pName) {
data = pVar;
variableName = pName;
};
~ttSaveObj() {};
std::string variableName;
T data;
};
ttGameObj.hpp:
#include "ttSaveObj.hpp"
class ttGameObj {
public:
ttGameObj();
~ttGameObj();
std::vector<ttSaveObj<void*>> data;
};
ttGameObj.cpp:
#include "ttGameObj.hpp"
ttGameObj::ttGameObj() {
int asdf = 5;
int * test = &asdf;
data.push_back(ttSaveObj<void*>(test, "X"));
std::cout << &data[0].data << " " << data[0].variableName << std::endl; //Output: 0x15fb770 X
}
Anything that will help me get closer to my intended outcome is appreciated, thanks!
The objects you put in the vector seem to have two data members: variableName, which is of fixed std::string type, and a data field, which is of varying type.
You may consider using C++17's std::variant (or Boost's variant implementation) for the data field. For example, if you plan to support the types int, float and std::string for your data, you can use a std::variant<int, float, std::string>.
There's also std::any, if you want to store instances of any type (that satisfy the requirements described in the std::any documentation).
In modern C++ I'd suggest to avoid the C-style void*, and use it only if strictly necessary (e.g. if you are at some legacy C API boundary): there are safer, more robust and higher-level alternatives to it.
Another option (if it makes better sense for your design) is to define a base class (interface) for the objects you want to put in your vector, and define custom classes that implement this interface. In this case, I suggest using smart pointers (like e.g. std::unique_ptr or std::shared_ptr) to manage those objects in a simple and safe way (I saw another answer here that used raw pointers, requiring explicit new/delete - actually in that code there were news but no delete, with consequent resource leaks).
E.g.:
#include <iostream>
#include <memory>
#include <string>
#include <vector>
using namespace std;
// Interface for an element to be inserted in the vector
class IElement
{
public:
IElement() {}
virtual ~IElement() {}
virtual string ToString() = 0;
// Other virtual methods ...
};
class IntElement : public IElement
{
public:
explicit IntElement(int n) : _n{ n } {}
virtual string ToString() override
{
return to_string(_n);
}
private:
int _n;
};
class StringElement : public IElement
{
public:
explicit StringElement(const string& s) : _s{ s } {}
virtual string ToString() override
{
return _s;
}
private:
string _s;
};
int main()
{
vector<shared_ptr<IElement>> elements;
elements.push_back(make_shared<IntElement>(10));
elements.push_back(make_shared<IntElement>(20));
elements.push_back(make_shared<StringElement>("Hello"));
elements.push_back(make_shared<StringElement>("World"));
for (const auto& e : elements)
{
cout << e->ToString() << '\n';
}
}
Output:
10
20
Hello
World
If you are using C++11 then you can use the tuple class in the standard library. You could make this object like so:
auto v = std::make_tuple(ttSaveObj(5, "int example"), ttSaveObj("Hello, world!", "string example"))
std::cout << std::get<0>(v).data << " " << std::get<0>(v).variableName << std::endl;
There is a drawback though that the index for access is a template argument and must therefore be known at compile time, meaning that you can't loop through the elements. Also the types of the elements in the tuple must be known at compile time.
If I understood your goals correctly, Java-like approach could take place, but you should wrap the vector to never forget the clean up.
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <string.h>
#include <memory>
using std::vector;
class Object
{
public:
explicit Object() {}
virtual ~Object() {}
virtual const char* toString() const = 0;
};
class StringObject : public Object
{
public:
explicit StringObject(const char* string) : Object()
{
if(string != 0)
{
m_value = new char[strlen(string) + 1];
strcpy(((char*)m_value), string);
} else
{
m_value = new char[1];
m_value[0] = 0;
}
}
virtual ~StringObject()
{
delete m_value;
}
virtual const char* toString() const
{
return (const char*)m_value;
}
private:
char* m_value;
};
class IntObject : public Object
{
public:
explicit IntObject(int val) : Object()
{
m_value = val;
}
virtual ~IntObject()
{
}
virtual const char* toString() const
{
return std::to_string(m_value).c_str();
}
private:
int m_value;
};
int main()
{
auto vec = vector<std::unique_ptr<Object>>();
vec.push_back(std::make_unique<IntObject>(9));
vec.push_back(std::make_unique<IntObject>(11));
vec.push_back(std::make_unique<StringObject>("hello"));
vec.push_back(std::make_unique<StringObject>("world"));
for(const auto& v : vec)
{
std::cout << v.get()->toString() << " ";
}
}
Output, as expected, "9 11 hello world".

c++ - help understanding differences between function and class templates

I'm trying to implement a C++ program that, given a list of elements, prints out unique elements from the list.
I know C a lot better than C++, but I am starting out on C++ practically (coding) only now.
I've only read up on C++ concepts what templates are and I'm comfortable with function templates but I just read up on class templates and I think I'm getting confused as to where to use which one, as applied to the scenario below.
Here's what I've written so far (*note that the function isUnique is supposed to be doing something else but I'm writing just verifiable actions inside it for now):
cppArrays.h
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
template <class T> class cpparray{
private:
int size;
vector<T> elems;
public:
cpparray(int);
~ cpparray();
int isUnique(T arr);
};
template <class T> cpparray<T>::cpparray(int size)
{
vector<T> elems(size);
cout << "Object created with size " << elems.size()<< "\n"<< endl;
}
template <class T> cpparray<T>::~cpparray()
{
cout << "Object del\n" << endl;
}
template <class T> int cpparray<T>::isUnique(T arr)
{
return arr.size();
}
cppArrays.cc
#include "cppArrays.h"
int main()
{
cpparray<int> a(10) ;
//a.push_back(1);
//a.push_back(2);
//cout << a.size() << a.begin() << a.end() << endl;
int b = isUnique(a);
return 0;
}
Details:
[1] I'm trying to use templates, because I want my vector to be able to be instantiated with any data type - char/float/int.
[2] I realize that in using a class template, by calling
cpparray<int>a(10);
I end up declaring an object a of class "cpparray" whose type is Integer. Is this correct?
If yes, then a.push_back(1) wouldn't work because it doesn't refer to the member variable but the object itself and hence it's understandable I'll get a compile time error saying no member named push_back in cpparray.
But this is making it even more difficult for me to
[1] understand when to use class template as opposed to function template,
[2] How do I initialize this vector in the template class and work with it, given my objective?
Your constructor should use initialization list to init members,
like this:
template <class T> array<T>::array(int sz) : size(sz), elems(sz)
{
cout << "Object created with size " << elems.size()<< "\n"<< endl;
}
What you did is to declare the vector as local in the constructor, init it to size, and the local vector was destroyed at the end of block.
Use a class template when you need a generic type that has compile-time variable properties. Template parameters can be types and constants, e.g.
template<typename T, size_t Size>
class MyArray {
T elements_[Size];
public:
MyArray() {}
// ...
};
Use a function template when wish to write a generic function that can be applied to various types/parameters:
#include <cstdio>
#include <iostream>
template<size_t BufSize, typename... Args>
int strprintf(char(&buf)[BufSize], const char* fmt, Args&&... args)
{
static_assert(BufSize > 0, "Buffer too small");
static_assert(BufSize < (1 << 31), "Buffer too large");
return snprintf(buf, BufSize, fmt, std::forward<Args>(args)...);
}
int main() {
char buf[16];
int printed = strprintf(buf, "hello world %s so long", "oversized load");
std::cout << buf << "\n";
}
http://ideone.com/SLUQX3
The above is an example of how you can replace one of those old vsnprintf forwarding printf-type functions; doing all the legwork at compile time makes it drastically more efficient.
BufSize can be deduced by the compiler because the type of buf is char[16]; it can capture the source by reference, the type is char and the array size - the template variable - is 16.
It's also possible to have a templated member function of a templated class:
template<typename T>
class Foo {
T t_;
public:
Foo() : t_() {}
Foo(const T& t) : t_(t) {}
template<typename RhsT>
bool is_same_size(const RhsT& rhs) {
return t_.size() == rhs.size();
}
};
This example will only work for instances when both T and RhsT have a size() member function, leading to the following:
Foo<vector<int>> fvi;
Foo<list<double>> fld;
fvi.is_same_size(fld); // fine
Foo<int> fi;
fvi.is_same_size(fi); // compiler error

How to add constructors/destructors to an unnamed class?

Is there a way to declare a constructor or a destructor in an unnamed class? Consider the following
void f()
{
struct {
// some implementation
} inst1, inst2;
// f implementation - usage of instances
}
Follow up question : The instances are ofcourse constructed (and destroyed) as any stack based object. What gets called? Is it a mangled name automatically assigned by the compiler?
The simplest solution is to put a named struct instance as a member in the unnamed one, and put all of the functionality into the named instance. This is probably the only way that is compatible with C++98.
#include <iostream>
#include <cmath>
int main() {
struct {
struct S {
double a;
int b;
S() : a(sqrt(4)), b(42) { std::cout << "constructed" << std::endl; }
~S() { std::cout << "destructed" << std::endl; }
} s;
} instance1, instance2;
std::cout << "body" << std::endl;
}
Everything that follows requires C++11 value initialization support.
To avoid the nesting, the solution for the construction is easy. You should be using C++11 value initialization for all members. You can initialize them with the result of a lambda call, so you can really execute arbitrarily complex code during the initialization.
#include <iostream>
#include <cmath>
int main() {
struct {
double a { sqrt(4) };
int b { []{
std::cout << "constructed" << std::endl;
return 42; }()
};
} instance1, instance2;
}
You can of course shove all the "constructor" code to a separate member:
int b { [this]{ constructor(); return 42; }() };
void constructor() {
std::cout << "constructed" << std::endl;
}
This still doesn't read all that cleanly, and conflates the initialization of b with other things. You could move the constructor call to a helper class, at the cost of the empty class still taking up a bit of space within the unnamed struct (usually one byte if it's the last member).
#include <iostream>
#include <cmath>
struct Construct {
template <typename T> Construct(T* instance) {
instance->constructor();
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
Construct c { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
} instance1, instance2;
}
Since the instance of c will use some room, we might as well get explicit about it, and get rid of the helper. The below smells of a C++11 idiom, but is a bit verbose due to the return statement.
struct {
double a { sqrt(4) };
int b { 42 };
char constructor { [this]{
std::cout << "constructed" << std::endl;
return char(0);
}() };
}
To get the destructor, you need the helper to store both the pointer to an instance of the wrapped class, and a function pointer to a function that calls the destructor on the instance. Since we only have access to the unnamed struct's type in the helper's constructor, it's there that we have to generate the code that calls the destructor.
#include <iostream>
#include <cmath>
struct ConstructDestruct {
void * m_instance;
void (*m_destructor)(void*);
template <typename T> ConstructDestruct(T* instance) :
m_instance(instance),
m_destructor(+[](void* obj){ static_cast<T*>(obj)->destructor(); })
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(m_instance);
}
};
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this };
void constructor() {
std::cout << "constructed" << std::endl;
}
void destructor() {
std::cout << "destructed" << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Now you're certainly complaining about the redundancy of the data stored in the ConstructDestruct instance. The location where the instance is stored is at a fixed offset from the head of the unnamed struct. You can obtain such offset and wrap it in a type (see here). Thus we can get rid of the instance pointer in the ConstructorDestructor:
#include <iostream>
#include <cmath>
#include <cstddef>
template <std::ptrdiff_t> struct MInt {};
struct ConstructDestruct {
void (*m_destructor)(ConstructDestruct*);
template <typename T, std::ptrdiff_t offset>
ConstructDestruct(T* instance, MInt<offset>) :
m_destructor(+[](ConstructDestruct* self){
reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(self) - offset)->destructor();
})
{
instance->constructor();
}
~ConstructDestruct() {
m_destructor(this);
}
};
#define offset_to(member)\
(MInt<offsetof(std::remove_reference<decltype(*this)>::type, member)>())
int main() {
struct {
double a { sqrt(4) };
int b { 42 };
ConstructDestruct cd { this, offset_to(cd) };
void constructor() {
std::cout << "constructed " << std::hex << (void*)this << std::endl;
}
void destructor() {
std::cout << "destructed " << std::hex << (void*)this << std::endl;
}
} instance1, instance2;
std::cout << "body" << std::endl;
}
Unfortunately, it doesn't seem possible to get rid of the function pointer from within ConstructDestruct. This isn't that bad, though, since its size needs to be non-zero. Whatever is stored immediately after the unnamed struct is likely to be aligned to a multiple of a function pointer size anyway, so there may be no overhead from the sizeof(ConstructDestruct) being larger than 1.
You can not declare a constructor or destructor for an unnamed class because the constructor and destructor names need to match the class name. In your example, the unnamed class is local. It has no linkage so neither mangled name is created.
If you are thinking of C++ names, then any class that has objects has to have a destructor whether you create it explicitly or not. So yes, the compiler knows how to assign a name. Whether that naming convention is any of your business, however, probably not.
Actually, you can create a structure or also a namespace without a name. You still need to have names somewhere because at the time you link all of that, the linker needs some kind of a name to make it all work, although in many cases it will be local names that are resolved immediately at compile time--by the assembler.
One way to know of the names assigned by the compiler is to look at the debug strings and see what corresponds to the different addresses that you're interested in. When you compile with -g then you should get all the necessary debug for your debugger to place your current at the right place with the right "names"... (I've see the namespaces without a name it says " namespace", I'm pretty sure structures use the same trick at a higher level.)