Placement new to avoid copy constructor - c++

I have a simple class that contains a pointer to one of it's own members:
struct X {
int val;
int* pVal;
X(int v) : val(v), pVal(&val) {}
}
X x(1);
I have some code like this:
void foo() {
doStuffWith(x);
x = X(2); // completely discard the old value of X, and start again
doStuffWith(x);
}
I'm worried that when x is reassigned, x.pVal will invalidly point to the member of the temporary X(2) if return value optimization does not occur.
I realize I could write a copy constructor to fix this. However, it seems wasteful to do the copy in the first place, rather than constructing the object in the right spot in memory to begin with.
Is it reasonable to use the placement new operator here? Or does this have unintented consequences for destructors?
void foo() {
doStuffWith(x);
new (&x) X(2); // completely discard the old value of X, and start again
doStuffWith(x);
}

The most obvious (and probably most effective) way to make this work is to provide copy assignment and copy construction operators to "do the right thing", something on this general order:
struct X {
int val;
int* pVal;
X(int v) : val(v), pVal(&val) {}
X(X const &other) : val(other.val), pVal(&val) {}
// pVal was already set by ctor, so just ignore it:
X &operator=(X const &other) { val = other.val; return *this; }
// and allow assignment directly from an int:
X &operator=(int n) { val = n; return *this; }
};
Then the rest of the code can just copy/assign X objects without jumping through hoops to prevent corruption.

No
It won't destruct the old value of x, but you're right the the default copy assignment operator won't do what you want either.

For me it seems quite acceptable solution if X's destructor will be called before placement new. It's syntactically allowed even the destructor is not actually specified for the class.
struct X {
int val;
int* pVal;
X(int v) : val(v), pVal(&val) {}
};
X x(1);
void foo() {
doStuffWith(x);
x.~X();
new (&x) X(2);
doStuffWith(x);
}
In this form it is a correct way to reuse memory for any object (but only if the object's ctor can't throw! otherwise UB may happen on program shutdown, i.e. double call of the destructor).
Indeed, the equality of pointers passed and returned from placement new in it non-array form is guaranteed by the standard:
18.6.1.3 Placement forms
...
void* operator new(std::size_t size, void* ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.
(and the result of the conversion to void* and then back to the same
pointer type is also guaranteed to be the same as the source pointer)
However, to avoid non-proper use of the class it would be more safe either define copy assignment and copy constructor or declare this class as noncopyable (with deleted ones)
And only the last (noncopyable) case may be regarded as a reason for using placement new.
Although I'm far from promoting placement new for general use, it express the intention to reuse object memory directly and doesn't rely on any optimization. Copy constructor and copy assignment are, of course, more safe, but don't express this intention excactly: no "copy" actually needed, the new object should be constructed in place of the old one.

Related

Pointer members of const struct

I have a class that looks somewhat like this:
class S
{
public:
int* data;
S() : data(new int[10]) {}
};
The constructor allocates the memory of 10 integers, and the default copy constructor as expected merely copies the pointer itself rather than the content.
Even if there is an instance of S that has const modifier, I can modify the data that data points to, since that data itself does not have const modifier. I could avoid this by making data private and only allowing write access via a non-const method like so:
class S
{
private:
int* data;
public:
S() : data(new int[10]) {}
int& operator(size_t i)
{
return data[i];
}
const int& operator(size_t i) const
{
return data[i];
}
};
But now I can use the copy constructor to circumvent the constness of the instance of S like so:
void main()
{
const S a; // Allocates memory
S b(a); // Also points to memory allocated for a
b(1) = 3; // Writes to a even though it is not supposed to be mutable
}
What would be an elegant way to solve this problem (potentially using templates)?
The data pointed to by an instance of const S should not be mutable at all using only this instance.
Copy constructor should only copy pointer, but not make a deep copy of the data.
Both a const S and an S should be creatable via a copy constructor given an instance of S such that the const instance cannot modify the data, but the non-const instance can.
It is possible to know in the copy constructor if the object being copied is const by providing two different copy constructors, one which takes a const parameter and one which does not. The compiler will select whichever version matches the passed parameter. Set a flag in the constructor so it can throw an error when a non-const operation is performed.
The best way to avoid the leaked memory shown in the question is to used a smart pointer like std::shared_ptr rather than a raw pointer. Unfortunately shared_ptr is meant for single objects, not arrays; workarounds are possible as in this StackOverflow question. I'm not going to try to solve this now, the code below still has the leak.
To be complete you should follow the Rule of Three and provide an operator= and destructor as well. I left this as an exercise for the reader.
class S
{
private:
int* data;
bool is_const;
public:
S() : data(new int[10]), is_const(false) { data[1] = 42; }
S(const S& other) : data(other.data), is_const(true) {}
S(S& other) : data(other.data), is_const(false) {}
int& operator()(size_t i)
{
if (is_const)
throw std::logic_error("non-const operation attempted");
return data.ptr[i];
}
const int& operator()(size_t i) const
{
return data.ptr[i];
}
};
See it in action: http://ideone.com/SFN89M
Delete the copy constructor (and assignment operator) for S. Create a new proxy class (SCopy) that holds a pointer to an S object (which is passed in to the constructor for SCopy). SCopy would then implement the const int &operator() const and not the non-const version.
This would then allow you to implement a destructor in S that would free the memory you're currently leaking.

How to correctly manage resources with move semantics?

struct foo{
int* i;
foo(): i(new int(42)){}
foo(const foo&) = delete;
foo(foo&&) = default;
~foo(){
std::cout << "destructor: i" << std::endl;
delete(i);
}
};
int main()
{
foo f;
auto sp_f = std::make_shared<foo>(std::move(f));
}
This is bad because it seems that the destructor of f will be called once it moves into the shared_ptr. The shared_ptr will have a deleted pointer and will delete it after it goes out of scope, which means the pointer will be deleted two times.
How do I avoid this problem?
You need to define the move constructor to prevent deletion from the moved-from object:
foo(foo&& f): i(f.i) {
f.i = nullptr;
}
Now when to destructor of the old object is run, it won't delete the i, since deleting a null pointer is a no-op.
You should also define a move assignment operator and delete the copy assignment operator too.
The rule of three is really the rule of five now. If you have a class that can be moved from, you should define the move semantics yourself (plus the copy, destructor, etc).
As to how to do that, to quote cppreference's page on std::move, "... objects that have been moved from are placed in a valid but unspecified state." The unspecified state is typically what the object would look like if it had been default initialized, or what would happen if the objects had swap called on them.
A straightforward way is, as #zenith has answered, is to have the move constructor (or assignment operator) set the original pointer to nullptr. This way the data isn't freed, and the original object is still in a valid state.
Another common idiom is, as mentioned, to use swap. If a class needs its own copy and move semantics, a swap method would be handy as well. The move constructor would delegate initialization to the default constructor, and then call the swap method. In a move assignment operator, just call swap. The object being moved into will get the resources, and the other object's destructor will free the original ones.
It would usually look like this:
struct Foo
{
void* resource; //managed resource
Foo() : resource(nullptr) {} //default construct with NULL resource
Foo(Foo&& rhs) : Foo() //set to default value initially
{
this->swap(rhs); //now this has ownership, rhs has NULL
}
~Foo()
{
delete resource;
}
Foo& operator= (Foo&& rhs)
{
this->swap(rhs); //this has ownership, rhs has previous resource
}
void swap(Foo& rhs) //basic swap operation
{
std::swap(resource, rhs.resource); //thanks #M.M
}
};

Explanation for below code snippet C++

I was reading C++11 Faq and came across this code. I have a better understanding of C++ coding, but I'm still not able to understand the below code.
template<class T>
class Handle {
T* p;
public:
Handle(T* pp) : p{pp} {}
~Handle() { delete p; } // user-defined destructor: no implicit copy or move
Handle(Handle&& h) :p{h.p} { h.p=nullptr; }; // transfer ownership
Handle& operator=(Handle&& h) { delete p; p=h.p; h.p=nullptr; return *this; } // transfer ownership
Handle(const Handle&) = delete; // no copy
Handle& operator=(const Handle&) = delete;
// ...
};
What does "transfer ownership" mean?
Why is the copy ctor equated to "delete"? how is it useful?
Please if someone can add a few examples with explanation, it would be a great help.
It's a move constructor, the special && syntax introduced in C++11 takes a rvalue reference, so a reference to a variable which has no name and can't be referenced anywhere else inside the code.
What happens in the constructor is that the Handle takes the ownership of the Handle passed through the move constructor in the way that it steals (pass me the term) the T* p inside by assigning its value to its own variable and then setting nullptr to the variable of the rvalue passed.
This is used because you don't really need to copy an rvalue, since that value won't be used anymore in the code, so it's safe to just take its data, this avoids a, possibly costly, copy constructor.
In C++ you had copy constructors and copy operators, which were expensive if your object was big. Now in C++11 you have move constructor and move operator which says "take everything from the source and kill it".
mybigthing y ;
...
mybigthing x( move(y)) ;
y is created with lots of stuff internally. after x(y), y is now empty and all the big stuff is in x.
One of the main reasons for this is to make returning big objects from functions free:
mybigthing f()
{
mybigthing tmp ;
...
return tmp ;
}
{
mybigthing y= f() ;
}
In c++03, this would be horrible performance wise. Now its free. The compilers are required to actually use y as the temporary inside of f() and never do any copies.
transfer ownership means if you do a=b the contents of b belong to a and does not exist in b anymore. This makes more sense in the example {A a; dosomething(a); return a;}. a exist locally in the function. It's contents are being moved into the return value. If A is a typedef for std::string it would mean the string internals have been moved instead of making a copy of a intentionally long string (html page maybe). However I believe string has a copy on write flag so it wouldn't make a copy in that situation but other classes may not bother to implement a copy on write.
The reason the constructor and assignment operator (which are move, not copy) delete is because the current p may be pointing to something. Not freeing it means a memory leak.
about your second question:
Why is the copy ctor equated to "delete"? how is it useful?
Here is an answer:
http://www.developerfusion.com/article/133063/constructors-in-c11/
C++11 Explicitly Deleted Constructors
C++11 also supports the concept of explicitly deleted constructors.
For example, you can define a class for which you do not want to write
any constructors and you also do not want the compiler to generate the
default constructor. In that case you need to explicitly delete the
default constructor:
class MyClass { public:
MyClass() = delete; };

Sane design for a class holding a shared resource

Consider the following simplified example of a class holding a shared resource:
class array
{
typedef std::array<float, 1000> resource;
public:
// default constructor, creates resource
array() : p_(std::make_shared<resource>()), a_(0), b_(1000) {}
// create view
array operator()(int a, int b) { return array(p_, a_+a, a_+b); }
// get element
float& operator[](int i) { return (*p_)[a_+i]; }
private:
std::shared_ptr<resource> p_;
int a_, b_;
// constructor for views
array(std::shared_ptr<resource> p, int a, int b) : p_(p), a_(a), b_(b) {}
};
Now I'm wondering how to define a semantics for this class that doesn't confuse its users. For example, I'd like to allow operator=() to copy elements:
array x, y;
x = y; // copies all elements from y's storage to x's
x(30,40) = y(50,60); // copies 10 elements
But then, to be consistent, shouldn't the copy constructor and the copy assignment operator always copy? What about:
array z = x(80,90); // will create an array referencing x's storage
In this case, the copy will be elided by the compiler, so no matter what my copy assignment operator does, z will hold a reference to x's storage. There's no way around this.
So does it make more sense for assignment to always create a reference, and copying to be declared explicitly? For example, I could define a wrapper class copy_wrapper, assignment of which forces copying of elements:
class copy_wrapper
{
array& a_;
public:
explicit copy_wrapper(array& a) : a_(a) {}
array& get() { return a_; }
};
class array
{
// ...
array& operator=(const array& a); // references
array& operator=(copy_wrapper c); // copies
copy_wrapper copy() { return copy_wrapper(*this); }
};
This would force users to write:
array x, y;
x(30,40) = y(50,60).copy(); // ok, copies
x(30,40) = y(50,60); // should this throw a runtime error?
x = y; // surprise! x's resource is destructed.
A bit cumbersome, and worse than that: not what you expect.
How should I deal with this ambiguity?
Does it make more sense for assignment to always create a reference, and copying to be declared explicitly?
In practice, no. Expecting developers to remember that a = b will not copy is what got std::auto_ptr into hot water. The C++11 standards committee also decided on std::move and std::forward to allow developers to explicitly say "I'm not making copies."
What about: array z = x(80,90); In this case, the copy will be elided by the compiler, so no matter what my copy assignment operator does, z will hold a reference to x's storage. There's no way around this.
This was your giveaway. You want "array" and "view to an array" to act differently, but you're representing them both with class array.
Implement a new class arrayview with a similar public interface and move the ranges a_ and b_ to arrayview.
array x, y;
x = y; // "array = array" copies all elements
x(30,40) = y(50,60); // "arrayview = arrayview" copies element range
arrayview v = x(80,90); // "arrayview(const arrayview&) shallow copies
x(30,40) = y; // NOT DEFINED, since this has no clear meaning
array z = x(80,90); // NOT DEFINED, since this has no clear meaning
Note that in your arrayview assignment operator, it should be valid to copy from an arrayview with the same resource, but in that specific case you should check whether std::copy_backward is needed instead of std::copy.

Can we return objects having a deleted/private copy/move constructor by value from a function?

In C++03 it is impossible to return an object of a class having a private non-defined copy constructor by value:
struct A { A(int x) { ... } private: A(A const&); };
A f() {
return A(10); // error!
return 10; // error too!
}
I was wondering, was this restriction lifted in C++11, making it possible to write functions having a class type return type for classes without constructors used for copy or move? I remember it could be useful to allow callers of a function use the newly returned object, but that they are not able to copy the value and store it somewhere.
Here is how it can work
A f() {
return { 10 };
}
This works even though A has no working copy or move constructor and no other constructor that could copy or move an A!
To make use of this feature of C++11, the constructor (taking int in this case) has to be non-explicit though.
The restriction has not been lifted. As per the access specifier, there is a note in §12.8/32 that explains:
two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided.
As of the deleted copy/move constructors §8.4.3/2 states that
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]
Not sure about this particular case, but my understanding of the quote is that, if after the overload resolution in §12.8/32 the deleted copy/move constructor is selected, even if the operation is elided, that could constitute a reference to the function, and the program would be ill formed.
The above code is still ill-formed in C++11. But you could add a public move constructor to A and then it would be legal:
struct A
{
A(int x) {}
A(A&&);
private:
A(A const&);
};
A f() {
return A(10); // Ok!
}
I was wondering, was this restriction lifted in C++11?
How could it be? By returning something by value, you are by definition copying (or moving) it. And while C++ can allow that copy/move to be elided in certain circumstances, it's still copying (or moving) by the specification.
I remember it could be useful to allow callers of a function use the returned object, but that they are not able to copy the value and store it somewhere.
Yes. You get rid of the copy constructor/assignment, but allow the value to be moved. std::unique_ptr does this.
You can return a unique_ptr by value. But in doing so, you are returning an "prvalue": a temporary that is being destroyed. Therefore, if you have a function g as such:
std::unique_ptr<SomeType> g() {...}
You can do this:
std::unique_ptr<SomeType> value = g();
But not this:
std::unique_ptr<SomeType> value1 = g();
std::unique_ptr<SomeType> value2 = g();
value1 = value 2;
But this is possible:
std::unique_ptr<SomeType> value = g();
value = g();
The second line invokes the move assignment operator on value. It will delete the old pointer and move the new pointer into it, leaving the old value empty.
In this way, you can ensure that the contents of any unique_ptr is only ever stored in one place. You can't stop them from referencing it in multiple places (via pointers to unique_ptr or whatever), but there will be at most one location in memory where the actual pointer is stored.
Removing both the copy and move constructors creates an immobile object. Where it is created is where it's values stay, forever. Movement allows you to have unique ownership, but without being immobile.
You could probably hack together a proxy to do the trick if you really wanted, and have a converting constructor that copies the value stored within the proxy.
Something along the lines of:
template<typename T>
struct ReturnProxy {
//This could be made private, provided appropriate frienship is granted
ReturnProxy(T* p_) : p(p_) { }
ReturnProxy(ReturnProxy&&) = default;
private:
//don't want these Proxies sticking around...
ReturnProxy(const ReturnProxy&) = delete;
void operator =(const ReturnProxy&) = delete;
void operator =(ReturnProxy&&) = delete;
struct SUPER_FRIENDS { typedef T GO; };
friend struct SUPER_FRIENDS::GO;
unique_ptr<T> p;
};
struct Object {
Object() : data(0) { }
//Pseudo-copy constructor
Object(ReturnProxy<Object>&& proxy)
: data(proxy.p ? proxy.p->data : throw "Don't get sneaky with me \\glare")
{
//steals `proxy.p` so that there isn't a second copy of this object floating around
//shouldn't be necessary, but some men just want to watch the world burn.
unique_ptr<Object> thief(std::move(proxy.p));
}
private:
int data;
Object(const Object&) = delete;
void operator =(const Object&) = delete;
};
ReturnProxy<Object> func() {
return ReturnProxy(new Object);
}
int main() {
Object o(func());
}
You could probably do the same in 03, though, using auto_ptrs. And it obviously doesn't prevent storage of the resultant Object, although it does limit you to one copy per instance.