placement new to circumvent assignment constructor - c++

Is it a viable solution to use placement new to circumvent copy assignment?
I have a member object that contains const members.
The object itself is meant to be created at runtime, but it's members are meant to be const.
I was wondering whether I could use placement new to circumvent the copy assignment at runtime?
#include <new>
#include <iostream>
struct A {
const int a;
A() : a(0) {};
A(int a) : a(a){}
};
struct B {
A a;
void createA() {
new(&a) A(69);
}
void useA() {
std::cout << a.a << std::endl;
}
};
int main(void) {
B b;
b.createA();
b.useA();
return 0;
}
It compiles and runs but does it invoke UB?

You should not do this, though it will technically work in this case.
By circumventing the copy assignment you are not giving the object a chance to perform any required cleanup on the old data (e.g. freeing memory resources). In this example, you are calling the new placement operator before the lifetime of a ends.
The following will work as it does not violate a's lifetime:
a.~A(); // manually destruct a, end it's lifetime
new(&a) A(69); // construct a new instance and start a new lifetime

Related

Is it OK to pass an unreferenced object as a parameter into a function?

Here is a super quick example of what I am thinking.
// Example program
#include <iostream>
#include <string>
class Obj
{
private:
int myInt;
public:
Obj()
{
myInt = 0;
}
~Obj()
{}
void increment()
{
myInt++;
}
int getInt()
{
return myInt;
}
};
class A
{
public:
Obj* myObj;
A()
{
myObj = nullptr;
}
~A()
{
if(myObj)
{
delete myObj;
myObj = nullptr;
}
};
void myFunc(Obj* o)
{
myObj = o;
}
};
int main()
{
A* a = new A();
a->myFunc(new Obj());
a->myObj->increment();
delete a;
}
Just as a hypothetical .... regarding the above code - specifically the line
a->myFunc(new Obj());
It compiles fine, but is there anything functionally wrong with doing this? Other than maybe poor form, or going against best practices?
An important problem with your code is that it's very fragile and bug-prone.
For example, what happens if you have two instances of class A, that point to the same Obj instance?
Suppose that one of the A instances is deleted. Then the object pointed by myObj is destructed. But now the other instance of A has a raw pointer that is pointing to a memory that is not valid anymore.
A better way of storing object pointers, assuming shared ownership semantic, is to use a smart pointer like std::shared_ptr.
For example, in class A replace the raw pointer Obj* myObj with a smart pointer like std::shared_ptr<Obj>, and don't explicitly invoke delete myObj from the A's destructor. Instead, let the std::shared_ptr's destructor automatically handle the deletion of the smart pointer data member. What will happen under the hood is that shared_ptr will use a reference count to figure out when there are no more references to the pointed object, and when this reference count goes to zero, the pointed object will be deleted.

What's the purpose of using a union with only one member?

When I was reading seastar source code, I noticed that there is a union structure called tx_side which has only one member. Is this some hack to deal with a certain problem?
FYI, I paste the tx_side structure below:
union tx_side {
tx_side() {}
~tx_side() {}
void init() { new (&a) aa; }
struct aa {
std::deque<work_item*> pending_fifo;
} a;
} _tx;
Because tx_side is a union, tx_side() doesn't automatically initialize/construct a, and ~tx_side() doesn't automatically destruct it.
This allows a fine-grained control over the lifetime of a and pending_fifo, via placement-new and manual destructor calls (a poor man's std::optional).
Here's an example:
#include <iostream>
struct A
{
A() {std::cout << "A()\n";}
~A() {std::cout << "~A()\n";}
};
union B
{
A a;
B() {}
~B() {}
};
int main()
{
B b;
}
Here, B b; prints nothing, because a is not constructed nor destructed.
If B was a struct, B() would call A(), and ~B() would call ~A(), and you wouldn't be able to prevent that.
In simple words, unless explicitly assigned/initialized a value the single member union does not initialize the allocated memory. This functionality can be achieved with std:: optional in c++17.

Using shared_from_this() without managed shared pointer in C++11

Let's say I have a class which is a child class of enable_shared_from_this. The documentation of this base class says there should be a shared pointer which owns this class before calling shared_from_this. Is it safe to allocate the class with new and call shared_from_this to manage the object?
As already mentioned by other users, calls to shared_from_this on instances that are not owned by shared_ptrs will result in an undefined behavior (usually an exception, but there are no guarantees).
So, why one more answer?
Because I did myself the same question once and got almost the same answer, then I started struggling with another question that immediately arose after that - how can I guarantee thus that all the instances are managed by a shared_ptr?
For the sake of completeness, I add another answer with a few details about this aspect.
Here a simple solution that had not been mentioned before.
So simple a solution, indeed: private constructors, factory method and variadic templates.
It follows a snippet that mixes all of them together in a minimal example:
#include<memory>
#include<utility>
class C: public std::enable_shared_from_this<C> {
C() = default;
C(const C &) = default;
C(C &&) = default;
C& operator=(const C &) = default;
C& operator=(C &&c) = default;
public:
template<typename... Args>
static std::shared_ptr<C> create(Args&&... args) noexcept {
return std::shared_ptr<C>{new C{std::forward<Args>(args)...}};
}
std::shared_ptr<C> ptr() noexcept {
return shared_from_this();
}
};
int main() {
std::shared_ptr<C> c1 = C::create();
std::shared_ptr<C> c2 = C::create(*c1);
std::shared_ptr<C> c3 = c2->ptr();
// these won't work anymore...
// C c4{};
// std::shared_ptr<C> c5 = std::make_shared<C>();
// std::shared_ptr<C> c6{new C{}};
// C c7{*c1};
// ... and so on ...
}
The basic (trivial?) idea is to forbid the explicit construction of new instances, but by using the factory method here called create.
Variadic templates are used to avoid writing several factory methods, nothing more. Perfect forwarding helps us to do that the right way.
Pretty simple, isn't it?
Anyway it took me a while to figure out that, so I hope this will help future readers once across the same doubt.
From the standard:
ยง 20.8.2.4
shared_ptr shared_from_this();
shared_ptr shared_from_this() const;
7 *Requires: enable_shared_from_this shall be an accessible base class of T. this shall be a
subobject of an object t of type T. There shall be at least one shared_ptr instance p that owns &t.
8 Returns: A shared_ptr object r that shares ownership with p.
9 Postconditions: r.get() == this
If you call shared_from_this() within a class that is not managed by a shared_ptr the result will be undefined behaviour because you have not fulfilled one of the documented preconditions of the method.
I know from experience that in [the current version of] libc++ the result is an exception being thrown. However, like all undefined behavior this must not be relied upon.
The documentation of this base class says there should be a shared pointer which owns this [object] before calling shared_from_this.
Okay, cool.
Is it safe to allocate the [object] with new and call shared_from_this to manage the object?
No. There should be a shared pointer which owns this [object] before calling shared_from_this.
No, it's not safe. You should only call shared_from_this if the object is managed by a shared_ptr, not allocated via new (without an associated shared_ptr). For example this code
struct Test: std::enable_shared_from_this<Test> {
std::shared_ptr<Test> getptr() {
return shared_from_this();
}
};
Test *test = new Test;
std::shared_ptr<Test> test2 = test->getptr();
will throw std::bad_weak_ptr (at least when using libstdc++). But this is OK:
std::shared_ptr<Test> test(new Test);
std::shared_ptr<Test> test2 = test->getptr();
This is not safe at all.
Calling shared_from_this() from a non-shared_ptr invokes a bad_weak_ptr exception.
#include <iostream>
#include <memory>
struct A : std::enable_shared_from_this<A>
{
A(A *parent, int x): parent(parent), x(x) {
std::cout << "create A with " << x << std::endl;
}
void print(){
std::cout << "print A : " << x << std::endl;
}
~A(){
std::cout << "delete A" << std::endl;
}
A *parent;
int x;
};
void useA(const std::shared_ptr<A> &a) {
a->print();
a->parent->print();
for(auto parent = a->parent; parent; parent = parent->parent){
auto aptr = parent->shared_from_this();
aptr->print();
}
}
int main() {
auto a1 = new A(NULL, 0);
auto p1 = std::make_shared<A>(a1, 1);
std::cout << "main" << std::endl;
useA(p1);
}
In this example, std::bad_weak_ptr is thrown at
auto aptr = parent->shared_from_this();

Avoid calling constructor of member variable

I have the following C++-class:
// Header-File
class A
{
public:
A();
private:
B m_B;
C m_C;
};
// cpp-File
A::A()
: m_B(1)
{
m_B.doSomething();
m_B.doMore();
m_C = C(m_B.getSomeValue());
}
I now would like to avoid the class A to call any constructor of C m_C. Because on the last line in A::A(), I'm anyways going to initialize m_C myself because I need to prepare m_B first. I could provide an empty default constructor for class B. But that's not the idea.
I have already tried to add m_C(NULL) to the init-list of A::A(). Sometimes it worked, sometimes it said there was no constructor taking NULL as an argument.
So how can I have m_C left uninitialized? I know that with pointers, the m_C(NULL)-way works. And I don't want to allocate it dynamically using new.
Any idea is appreciated.
How about using technique described in this QA?
Prevent calls to default constructor for an array inside class
std::aligned_storage<sizeof(T[n]), alignof(T)>::type
Or, you also can consider using of union. AFAIK, unions will be initialized only with first named member's constructor.
For example,
union
{
uint8_t _nothing = 0;
C c;
};
According to the standard mentioned in the QA, c will be zero-initialized, and its constructor will not be called.
You can't.
All member variables are full constructed when the construcotr code block is entered. This means there constructors must be called.
But you can work around this restriction.
// Header-File
class A
{
struct Initer
{
Initer(B& b)
: m_b(b)
{
m_b.doSomething();
m_b.doMore();
}
operator int() // assuming getSomeValue() returns int.
{
return m_b.getSomeValue();
}
B& m_b;
};
public:
A();
private: // order important.
B m_B;
C m_C;
};
// cpp-File
A::A()
: m_B(1)
, m_C(Initer(m_B))
{
}
I don't see a good way to achieve what you want. This must be a workaround:
// Header-File
class A
{
public:
A();
private:
B m_B;
C m_C;
static int prepareC(B& b);
};
// cpp-File
A::A()
: m_B(1)
, m_C(prepareC(m_B))
{
}
int A::prepareC(B& b)
{
b.doSomething();
b.doMore();
return b.getSomeValue();
}
Please ensure that m_B.doSomething(), m_B.doMore() and m_B.getSomeValue() don't touch m_C (directly or indirectly).
As #Tobias correctly mentions, this solution depends on the order of initialization. You need to ensure that the definitions of m_B and m_C are in this order.
Updated the code according to #Loki's idea.
What you ask is forbidden - and correctly so. This ensures that every member is correctly initialized. Do not try to work around it - try to structure your classes that they work with it.
Idea:
C has a constructor that does nothing
C has an initialization method that makes the class usable
C tracks whether it has been initialized correctly or not and returns appropriate errors if used without initialization.
The pointer sounds like the only clean solution to me. The only other solution I see is to have a default constructor for C that does nothing and have an initialising method in C you call yourself later.
m_C.Initialise( m_B.getSomeValue() );
Easiest is storing pointers to a B and a C. These can be initialized to 0, omitting any construction. Be careful not to dereference a null pointer and delete it in the destructor of A (or use std::unique_ptr/boost::scoped_ptr).
But why not initialize m_B first (through a proper constructor call, not in A::A(), and then use that initialized B instance to initialize m_C? It will call for a small rewrite, but I bet it'll be worth the code cleanup.
If you don't want to allocate it dynamically using new for code clutter/exception safety reasons, you can use a std::unique_ptr or std::auto_ptr to solve this problem.
A solution that avoids new is to edit C to have a two-step initialization process. The constructor would then construct a "zombie" object, and you'd have to call an Initialize method on that m_C instance to finish your initialization. This is similar to the existing cases you found where you could pass NULL to the constructor, and later go back to initialize the object.
Edit:
I thought of this earlier (even though it looks much like other people's solutions). But I had to get some confirmation that this wouldn't break before I added this solution - C++ can be quite tricky, and I don't use it very often :)
This is cleaner than my other suggestions, and doesn't require you to mess with any implementation but that of A.
Simply use a static method as the middle-man on your initialization:
class A
{
public:
A();
private:
static int InitFromB(B& b)
{
b.doSomething();
b.doMore();
return b.getSomeValue();
}
// m_B must be initialized before m_C
B m_B;
C m_C;
};
A::A()
: m_B(1)
, m_C(InitFromB(m_B))
{
}
Note that this means you can't allow m_B to depend on the instance of A or C at all, whereas the solutions at the top of this answer might allow you to pass A or m_C into m_B's methods.
Just use comma expressions:
A::A()
: m_B(1)
, m_c(m_B.doSomething(), m_B.doMore(), m_B.getSomeValue())
{
}
Obviously, as others have explained, m_B better be declared before m_C else m_B.doSomething() invokes undefined behavior.
Here we have the building blocks:
#include <iostream>
class C
{
public:
C(int i){std::cout << "C::C(" << i << ")" << std::endl;}
};
class B
{
public:
B(int i){std::cout << "B::B(" << i << ")" << std::endl;}
void doSomething(){std::cout << "B::doSomething()" << std::endl;}
void doMore(){std::cout << "B::doMore()" << std::endl;}
int getSomeValue(){return 42;}
};
If you want to make a new kind of construction for B consider making a derived class:
class B1 : public B
{
public:
B1() : B(1)
{
doSomething();
doMore();
}
};
Now use the class B1 that is derived from B:
class A
{
private:
B1 _b;
C _c;
public:
A() : _c(_b.getSomeValue()){std::cout << "A::A()" << std::endl;}
};
And then:
int main()
{
A a;
}
Output:
B::B(1)
B::doSomething()
B::doMore()
C::C(42)
A::A()

auto_ptr baffling behaviour

#include<iostream>
#include<memory>
#include<stdio>
using namespace std;
class YourClass
{
int y;
public:
YourClass(int x) {
y= x;
}
};
class MyClass
{
auto_ptr<YourClass> p;
public:
MyClass() //:p(new YourClass(10))
{
p= (auto_ptr<YourClass>)new YourClass(10);
}
MyClass( const MyClass &) : p(new YourClass(10)) {}
void show() {
//cout<<'\n'<<p; //Was not working hence commented
printf("%p\n",p);
}
};
int main() {
MyClass a;
a.show();
MyClass b=a;
cout<<'\n'<<"After copying";
a.show();//If I remove copy constructor from class this becomes NULL(the value of auto_ptr becomes NULL but if class has copy constructor it remains same(unchanged)
b.show();//expected bahavior with copy construcotr and withought copy constructor
}
Making the problem more specific:
Currently the class has copy constructor so there is no problem with the value of auto_ptr printed by a.show()(when it is called second time). It remians the same as it was when it was initiazed). It remians unchanged.
If I remove the copy contructor from the class MyClass , the value of auto_ptr printed by a.show()(when it is called second time) is NULL.
What's happening is due to the strange (but only justifiable if you think about it) semantics of assigning or copying an auto_ptr, e.g.
auto_ptr<T> a;
auto_ptr<T> b(new T());
a = b;
... or ...
auto_ptr<T> b(new T());
auto_ptr<T> a(b);
These will set a to b as expected, but they will also set b to NULL (see http://www.cplusplus.com/reference/std/memory/auto_ptr/auto_ptr/).
If you don't define a copy constructor for MyClass, then the compiler will generate one for you and will do just something similar to the above when it copies the auto_ptr member. Hence the copied from class will have a NULL member after the copy constructor has been called.
You shouldn't be casting your class to the autoptr. I know that for sure. I am not sure off the top of my head what syntax it wants but it should be something like p = new YourClass().