The problem is that normally you need an already existing object on which to call the functions (unless it is a static function), so for the constructor that's a bit of a an issue when you want to do it in a nonstandard way.
Here's how to create a new class object in existing memory without using new
. This will even work with raw memory from malloc()
, provided you first memset()
the memory to zeros.
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <vector>
class Str_obj{
public:
char* str;
constexpr Str_obj(const Str_obj& obj) = default;
Str_obj(const char* str1){
str = strdup(str1);
puts("ctor");
puts(str);
}
~Str_obj(){
puts("dtor");
puts(str);
free(str);
str = nullptr;
}
Str_obj& operator = (const Str_obj& obj){
puts("copy assign");
free(str);
str = strdup(obj.str);
return *this;
}
Str_obj& operator = (Str_obj&& obj){
puts("move assign");
free(str);
str = obj.str;
obj.str = nullptr;
return *this;
}
};
std::vector<std::string>
to_string_vec(Str_obj* arr, size_t len){
std::vector<std::string> str_arr(len);
for(int i = 0; i < len; ++i){
str_arr[i] = std::string(arr[i].str);
}
return str_arr;
}
int main() {
std::cout<<"Creating objects:\n";
constexpr size_t len = 2;
Str_obj arr[len] = {
Str_obj("I'm the first object"),
Str_obj("I'm the 2nd")
};
std::vector<std::string> str_arr1 = to_string_vec(arr, len);
std::cout<<"\n";
std::cout<<"Destruct and replace object:\n";
arr[0].~Str_obj(); // call destructor
// Calls constructor, then move assign to existing memory.
arr[0] = std::move(Str_obj("I'm the 3rd object in place of first"));
std::vector<std::string> str_arr2 = to_string_vec(arr, len);
std::cout<<"\n";
for(int i = 0; i < len; ++i){
std::cout<<i<<". "<<str_arr1[i]<<"\n";
}
std::cout<<"\n";
for(int i = 0; i < len; ++i){
std::cout<<i<<". "<<str_arr2[i]<<"\n";
}
return 0;
}
Possible output:
Creating objects:
ctor
I'm the first object
ctor
I'm the 2nd
Destruct and replace object:
dtor
I'm the first object
ctor
I'm the 3rd object in place of first
move assign
dtor
0. I'm the first object
1. I'm the 2nd
0. I'm the 3rd object in place of first
1. I'm the 2nd
dtor
I'm the 2nd
dtor
I'm the 3rd object in place of first
do_smth_useful
, perhaps also call it from the destructor, and then useoperator=
or a "set" function for the new value. – PasserbyObject1
is actually going to a template parameter, and it's not your container's fault that it's broken. In that case I withdraw my objection to using placement new, Your Honour, but it should still be noted for the record thatObject1 o; mycontainer.push_back(o);
will result in undefined behaviour sooner or later. – Passerbyvoid pop()
, when deleting object from container. As I want to use array of objects (not pointer) to be stored in container, I will need to destruct one, but not use delete for it. – RachabaObject1
, not in the placement new technique. Its copy constructor and assignment operator result in two objects sharing the samemalloc
ed buffer. You should either implement them, or else declare them private member functions (and not define them). – Passerby