I have code similar to this:
MyClass createInstance()
{
MyClass t;
t.setValue(20);
return t;
}
int main()
{
MyClass primary;
primary.setValue(30);
primary = createInstance();
}
My problem is that createInstance() creates a temporary that is deleted later. In my case, it doesn't use RVO, I have to use The Rule of Three (because my class has a pointer to data members), and I have to do a deep copy of Megabytes of data.
I wonder what's the best way to prevent the creation of a temporary?
Furthermore, I have this MyClass as a member of another class and I would like to prevent the indirection of a pointer and the requirement to manually delete it in the destructor of my parent class.
For example, I could use pointers instead (which would require me to explicitly call the destructor:
MyClass *createInstance()
{
MyClass *t = new MyClass();
t->setValue(20);
return t;
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = createInstance();
}
Or I could use a member function:
void MyClass::createNewInstance()
{
~MyClass();
init();
setValue(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
primary.createNewInstance();
}
Or I could disallow Assignment/Copying in general:
void MyClass::createInstance()
{
setValue(20);
}
int main()
{
MyClass *primary = new MyClass();
primary->setValue(30);
delete primary;
primary = new MyClass();
primary->createInstance();
}
Am I missing something?
You can't (N)RVO copy into a pre-existing object. The optimization is all about using another freshly created object instead of copying, but in this case the compiler can't guarantee that the assignment object doesn't leave some of the existing state alone (for example).
I would expect that MyClass primary(createInstance()); would enable NRVO for you.
If you really need to assign from a create function your choices are at least two: You can create a temporary and then swap, avoiding the data copy. Alternately with C++11 you could move into the existing object.
Just like what paddy said, how do you know it's not using RVO?
The compiler will do many thing to optimize your code, if it's not in debugging mode.
But, in your creatInstance function, you create a local object, and call a member function on it. The calling of the member function ( t->setValue(20) ) makes it difficult to be optimized, because the compiler will think, the local object is more useful than just an return value. Clearly, we know the local t can be optimized out, but the compiler may not be able to analyze this from its context.
And, by the meaning of "creatInstance", it seems that you just want creat an instance and return it. So, if your constuctor allows to set the value directuly, you can use the RVO:
MyClass creatInstance()
{
return MyClass(20); // if your constuctor makes it possible
}
then, your code will be optimized to this:
// C++ psuedocode
void creatInstance(MyClass* ptr)
{
new (ptr) MyClass(20);
}
int main()
{
MyClass primary;
primary.setValue(30);
// primary = createInstance();
MyClass __temp; // default constructor not called!
creatInstance(&__temp);
primary.operator=(__temp);
// destruct the __temp
}
You may think, it still has to creat temporary object __temp and destroy it , yes, but in your original code, you will creat two temporary object and destroy them, one in your main stack frame, one in your creatInstance function's stack frame.
If you can not sustain the cost of creating temporary object and those stuff, I think you can just change your idea to this:
void modifyInstance(Myclass& objToBeModified)
{
objToBeModified.setValue(20);
// do any change
}
and call it by : modifyInstance ( primary );
by this way, the temporary object creation is definitely prevented!
After all, you just want to change the primary by calling a function, why not writting it directly like above?
Related
Have looked at various similar questions here but still can't figure out why the following code does not compile:
// these three are defined somewhere
class A;
std::unique_ptr<A> make_a();
void take_a(std::unique_ptr<A>&&);
int main(){
take_a(make_a()); // this fails
return 0;
}
According to this:
If the default deleter is used, T must be complete at the point in
code where the deleter is invoked, which happens in the destructor,
move assignment operator, and reset member function of
std::unique_ptr.
As far as I understand, none of these (destructor, move assignment operator, nor reset member function) happens in main.
So why does compiler needs the definition of A here?
Since main has a unique_ptr within its scope, realistically it would need to know how to delete the object it holds.
It's possible that take_a doesn't actually take ownership of the object, thus main would need to delete.
main gets a temporary unique_ptr from make_a(), let's call it X. It then passes an rvalue reference to X to take_a. It still has the destroy X. Hence, it has to call the destructor after take_a, even though X would typically be empty at that point.
We need class A description (at least constructor and destructor) in order to create and move std::unique_ptr<A> objects; take_a(make_a()) is creating such object because make_a() is pass-by-value. It first creates a new unique_ptr<A> object, initialize it (using default constructor), and then update its value and returns this new object. Here the default constructor/destructor is being used, which the compiler is unable to find.
#include <bits/stdc++.h>
class A {
public: A() {}
public: ~A() {}
};
std::unique_ptr<A> make_a() {
std::cout << "make";
std::unique_ptr <A> tt = nullptr;
return tt;
}
void take_a(std::unique_ptr<A>&&) {
std::cout << "take";
}
int main(){
take_a(make_a()); // this works now
return 0;
}
Edit: Forgot to add the link. Works the other way too.
Consider the following class:
struct S { ~S() = delete; };
Shortly and for the purpose of the question: I cannot create instances of S like S s{}; for I could not destroy them.
As mentioned in the comments, I can still create an instance by doing S *s = new S;, but I cannot delete it as well.
Therefore, the only use I can see for a deleted destructor is something like this:
struct S {
~S() = delete;
static void f() { }
};
int main() {
S::f();
}
That is, define a class that exposes only a bunch of static functions and forbid any attempt to create an instance of that class.
What are the other uses (if any) of a deleted destructor?
If you have an object which should never, ever be deleted or stored on the stack (automatic storage), or stored as part of another object, =delete will prevent all of these.
struct Handle {
~Handle()=delete;
};
struct Data {
std::array<char,1024> buffer;
};
struct Bundle: Handle {
Data data;
};
using bundle_storage = std::aligned_storage_t<sizeof(Bundle), alignof(Bundle)>;
std::size_t bundle_count = 0;
std::array< bundle_storage, 1000 > global_bundles;
Handle* get_bundle() {
return new ((void*)global_bundles[bundle_count++]) Bundle();
}
void return_bundle( Handle* h ) {
Assert( h == (void*)global_bundles[bundle_count-1] );
--bundle_count;
}
char get_char( Handle const* h, std::size_t i ) {
return static_cast<Bundle*>(h).data[i];
}
void set_char( Handle const* h, std::size_t i, char c ) {
static_cast<Bundle*>(h).data[i] = c;
}
Here we have opaque Handles which may not be declared on the stack nor dynamically allocated. We have a system to get them from a known array.
I believe nothing above is undefined behavior; failing to destroy a Bundle is acceptable, as is creating a new one in its place.
And the interface doesn't have to expose how Bundle works. Just an opaque Handle.
Now this technique can be useful if other parts of the code need to know that all Handles are in that specific buffer, or their lifetime is tracked in specific ways. Possibly this could also be handled with private constructors and friend factory functions.
one scenario could be the prevention of wrong deallocation:
#include <stdlib.h>
struct S {
~S() = delete;
};
int main() {
S* obj= (S*) malloc(sizeof(S));
// correct
free(obj);
// error
delete obj;
return 0;
}
this is very rudimentary, but applies to any special allocation/deallocation-process (e.g. a factory)
a more 'c++'-style example
struct data {
//...
};
struct data_protected {
~data_protected() = delete;
data d;
};
struct data_factory {
~data_factory() {
for (data* d : data_container) {
// this is safe, because no one can call 'delete' on d
delete d;
}
}
data_protected* createData() {
data* d = new data();
data_container.push_back(d);
return (data_protected*)d;
}
std::vector<data*> data_container;
};
Why mark a destructor as delete?
To prevent the destructor from being invoked, of course ;)
What are the use cases?
I can see at least 3 different uses:
The class should never be instantiated; in this case I would also expect a deleted default constructor.
An instance of this class should be leaked; for example, a logging singleton instance
An instance of this class can only be created and disposed off by a specific mechanism; this could notably occur when using FFI
To illustrate the latter point, imagine a C interface:
struct Handle { /**/ };
Handle* xyz_create();
void xyz_dispose(Handle*);
In C++, you would want to wrap it in a unique_ptr to automate the release, but what if you accidentally write: unique_ptr<Handle>? It's a run-time disaster!
So instead, you can tweak the class definition:
struct Handle { /**/ ~Handle() = delete; };
and then the compiler will choke on unique_ptr<Handle> forcing you to correctly use unique_ptr<Handle, xyz_dispose> instead.
There are two plausible use cases. First (as some comments note) it could be acceptable to dynamically allocate objects, fail to delete them and allow the operating system to clean up at the end of the program.
Alternatively (and even more bizarre) you could allocate a buffer and create an object in it and then delete the buffer to recover the place but never prompt an attempt to call the destructor.
#include <iostream>
struct S {
const char* mx;
const char* getx(){return mx;}
S(const char* px) : mx(px) {}
~S() = delete;
};
int main() {
char *buffer=new char[sizeof(S)];
S *s=new(buffer) S("not deleting this...");//Constructs an object of type S in the buffer.
//Code that uses s...
std::cout<<s->getx()<<std::endl;
delete[] buffer;//release memory without requiring destructor call...
return 0;
}
None of these seems like a good idea except in specialist circumstances. If the automatically created destructor would do nothing (because the destructor of all members is trivial) then the compiler will create a no-effect destructor.
If the automatically created destructor would do something non-trivial you very likely compromise the validity of your program by failing to execute its semantics.
Letting a program leave main() and allowing the environment to 'clean-up' is a valid technique but best avoided unless constraints make it strictly necessary. At best it's a great way to mask genuine memory leaks!
I suspect the feature is present for completeness with the ability to delete other automatically generated members.
I would love to see a real practical use of this capability.
There is the notion of a static class (with no constructors) and so logically requiring no destructor. But such classes are more appropriately implemented as a namespace have no (good) place in modern C++ unless templated.
Creating an instance of an object with new and never deleting it is the safest way to implement a C++ Singleton, because it avoids any and all order-of-destruction issues. A typical example of this problem would be a "Logging" Singleton which is being accessed in the destructor of another Singleton class. Alexandrescu once devoted an entire section in his classical "Modern C++ Design" book on ways to cope with order-of-destruction issues in Singleton implementations.
A deleted destructor is nice to have so that even the Singleton class itself cannot accidentally delete the instance. It also prevents crazy usage like delete &SingletonClass::Instance() (if Instance() returns a reference, as it should; there is no reason for it to return a pointer).
At the end of the day, nothing of this is really noteworthy, though. And of course, you shouldn't use Singletons in the first place anyway.
Real example is obviously much longer, but this sums up my problem:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Object(int param1);
Object::Object(int param1, int param2);
};
Object::Object(){}
Object::Object(int param1):mInt1(param1){}
Object::Object(int param1, int param2):mInt1(param1),mInt1(param2){}
Then in main:
if (type1){
Object instance(param1);
}
else{
Object instance(param1,param2);
}
// do stuff with instance
Whoops! That won't work, instance is out of scope for the program that follows.
Object instance;
if (type1){
instance = Object(param1);
}
else{
instance = Object(param1,param2);
}
// do stuff with instance
But now I run in to trouble because I didn't have a copy constructor defined. I'd really rather not write a copy-constructor because my actual class has dozens of members, many of which are non-basic types and might require even more work to copy.
Specifically, I am getting
main.cpp: error: use of deleted function ‘Object& Object::operator=(Object&&)’
instance = Object(param1);
^
note: ‘Object& Object::operator=(Object&&)’ is implicitly deleted because the default definition would be ill-formed:
The universal way to deal with non-copyable objects is to throw it into a unique_ptr (or auto_ptr, depending on your compiler).
std::unique_ptr<Object> instance;
if (type1) {
instance.reset(new Object(i));
}
else {
instance.reset(new Object(i, j));
}
Using raw pointers here really isn't safe because once you start having to deal with exceptions or any interesting code paths it becomes a chore to worry about leaks. Trust me, in 100% of cases, you will have less work and lines of code to deal with if you just drop it in a unique_ptr.
An optimal solution would be to redesign Object's constructors, because circumventing non-copyability may leave the object in an illegal state. In general, you want to preserve non-copyability if the compiler thinks it's necessary. We don't have the details here to flesh out such a solution however.
If you do not want dynamically allocation then you can use an Initialize function:
class Object
{
int mInt1,mInt2;
Object::Object();
Object::Initialize();
Object::Initialize(int param1);
Object::Initialize(int param1, int param2);
};
Object::Object(){Initialize();} //call the empty Initialize for nice coding...:)
Object::Initialize(){ }
Object::Initialize(int param1){ mInt1(param1); }
Object::Initialize(int param1, int param2){ mInt1(param1);mInt1(param2);}
Then you can use initialize to select the type.
Object instance;
if (type1){
instance.Initialize(param1);
}
else{
instance.Initialize(param1,param2);
}
Here is a low-level(ish) solution which does what you want. I will leave it up to you to decide whether it's a good idea to use it:
#include <type_traits>
template <class T>
class MultiInitialiser
{
T *object;
std::aligned_storage<T> storage;
public:
MultiInitialiser() : object(nullptr)
{}
template <class... Arg>
void initialise(Arg &&... arg)
{
if (object)
throw "Double init error";
object = new (&storage) T(std::forward<Arg>(arg)...);
}
operator T& ()
{ return *object; }
operator const T& () const
{ return *object; }
~MultiInitialiser()
{
if (object)
object->~T();
}
};
Copy/move operations for the above are left as an excercise for the reader ;-)
The class would then be used like this:
MultiInitialiser<Object> instance;
if (type1){
instance.initialise(param1);
}
else{
instance.initialise(param1,param2);
}
Apart from the cast to T, you could also give the class operator* and operator-> returning the contained object, similar to what boost::optional does.
There are a couple of options that let you do this while retaining automatic storage, and which one you should use depends on the semantics of the type Object.
The POD
If you have a type like the one given in the question, you might choose to reduce it to a POD type; basically, remove all of the user-provided constructors and give everything the same access specifier:
struct Object {
int mInt1, mInt2;
};
Then, your initialization pattern might look like this (using placement new):
Object o; // Default-initialized, a no-op
if (condition)
new (&o) Object {i};
else
new (&o) Object {i, j};
General Types
Generally speaking, your typical value-semantic type will work perfectly fine if you default-initialize and then assign, thanks to move semantics:
std::vector <foo> v;
if (condition)
v = std::vector <foo> (42);
else
v = std::vector <foo> {bar, baz, quux};
Often, though, you'll still be doing work in the default constructor, because certain types' default-constructed objects (e.g., std::vector) have well-defined state. If you want to avoid this work for an arbitrary predefined type, you might want to use std::optional (as of this writing not actually yet standard):
std::optional <big_but_flat> b;
if (condition)
b.emplace (i);
else
b.emplace (i, j);
Without std::optional
You might object that std::optional has too much overhead associated with it, and I'll leave it to you and your measurements to decide whether that's the case. At any rate, we can get our behaviour without worrying about that overhead— but may the nasal demons have mercy if you don't actually perform your initialization. We'll use a union to get what we want:
// At function scope
union store_v {
std::vector <int> v;
store_v () {}
~store_v () { v.~vector <int> (); }
} sv;
if (condition)
new (&sv.v) std::vector <int> (42);
else
new (&sv.v) std::vector <int> {49, 343, 2401};
This may be improved. For example, we can make the storage a template:
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
store <std::vector <int>> sv;
if (condition)
new (&sv.t) std::vector <int> (42);
else
new (&sv.t) std::vector <int> {49, 343, 2401};
We can give ourselves a reference:
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
store <std::vector <int>> sv;
auto&& v = sv.t; // Deduce const, for what that's worth
if (condition)
new (&v) std::vector <int> (42);
else
new (&v) std::vector <int> {49, 343, 2401};
And with a little attention to detail to avoid name collisions and handle C++'s… interesting declaration syntax, we could even define a couple of macros to clean the code up (implementation left as an exercise to the reader):
template <typename T>
union store {
T t;
store () {}
~store () { t.~T (); }
};
// At function scope
DECL_UNINIT (std::vector <int>, v);
if (condition)
INIT (v, (42));
else
INIT (v, {49, 343, 2401});
You can use a pointer to your object and instantiate it by new operator:
Object * instance;
if (type1){
instance = new Object(param1);
}
else{
instance = new Object(param1,param2);
}
You're using something that is called copy elision.
This states that the compiler MAY optimize the code and avoid a copy constructor in such a case.
But it doesn't have to, and may use a copy constructor anyway.
The right way (without being subjected to the whims of the compiler) would be to use a pointer:
Object* instance;
if (type1){
instance = new Object(param1);
}
else{
instance = new Object(param1,param2);
}
In your version of one-parameter constructor, the mInt2 member is just ignored (isn't ever initialized), so I assume that you don't do any computation with that member if type1 is false (though I don't know how you're doing it without storing type1).
So, why don't just change the dessign? Make te constructor take int param1, int param2 and type1 as parameters and choose internally how to build himself:
class Object
{
int mInt1,mInt2;
Object::Object() :
mInt1(0), // don't forget to initialize your values!
mInt2(0)
{}
// Object::Object(int param1); no more 1-parameter ctor.
Object::Object(int param1, int param2, type type1) :
mInt1(param1),
mInt2(type1 ? param2 : 0) // assuming that 0 isn't a valid value for mInt2
{}
};
Then in main:
Object instance(param1, param2, type1);
// do stuff with instance
I guess that it looks a little neater.
You could write a move assignment. Depending what your data members look like, you may get away with memcopying some or all of them, cf. Move constructor with memcpy.
That said, I assume that either you need a full set of constructors/destructors, including copy and assignment; that will always be necessary if you want to have it in containers, assign it etc. Or else the class doesn't need any of that and you just initialize the needed parts of it depending on the situation, and when you are done, you de-initialize manually.
I think I found a way to do it without requiring allocating the object on the heap, using a lambda.
Basically, the idea is to separate the construction from the usage. (the following assume that you fixed the difinition of Object so that it compiles)
auto work = []( Object& object ){
// here do the work on the object
};
// now create the object and apply the work in the process:
if (type1){
Object instance(param1);
work( instance );
}
else{
Object instance(param1,param2);
work( instance );
}
Here no copy was involved but the same code is still applied whatever the wy the object was constructed, and without having to declare an external function (as a lambda is a local function).
From the memory point of view, there will always be only one instance object so the stack memory allocated will always be the same size whatever the path.
Obviously, this don't work if the instance have to get out of the scope of the whole function. If it's the case, then you really need to allocate it on the heap using a smart pointer preferably.
My programming background is the Java world, but I've just started learning C++. I've stumbled across this rather trivial and probably pretty noobish problem that somehow puzzles me as a Java programmer:
I have a class with an array which is initialized via new in the constructor and deleted in the destructor. Now when I create an object of this class and assign another object of this class to the same variable (at least that is what I think it is), the delete[] method in the destructor seems to be called twice when the variables leave the scope (in this case the main() function) (the debugger gives me an _BLOCK_TYPE_IS_VALID assertion failed warning).
Why is that? Why isn't the deconstructor called before I assign a new object to f? How could I explicitely delete Foo(1)? What exactly happens here?
class Foo{
private:
int *field;
public:
Foo(int size){
field = new int[size];
}
~Foo(){
delete[] field;
}
};
int main(){
Foo f = Foo(1);
f = Foo(2);
}
There is something in the C++ world called the Rule Of Three.
A class will automatically generate a destructor, copy constructor, and assignment operator for you.
If you have to manually define one of those functions, you probably have to define all three of them.
In your case, you should define the two copy functions, so that a copy of Foo gets its own copy of field. Add these two functions:
class Foo{
Foo( const Foo &f ) {
size = f.size;
field = new int[size];
std::copy( f.field, f.field + size, field );
}
Foo& operator=( const Foo &f ) {
// Leverage the logic that was already written in the copy constructor
Foo tmp(f);
std::swap( *this, temp );
return *this;
}
};
Note that I'm assuming that you've stored size in the Foo object. You would probably need to store that information anyway in a real-life application
You're not following the rule of three, which is bad. Because the default copy constructor does a shallow copy, all your automatic variables (f and the temporaries) have the field member pointing to the same int, which is destroyed multiple times when the destructor is called.
Implement a proper copy constructor, or use C++ idioms and avoid manual management alltogether - i.e. use a std::vector instead.
myClassVar = MyClass(3);
I expected destructor being called on the previously created myClassVar on the left.
But it is actually being called on the new object that's created by MyClass(3).
My full test code and output follows..
edit
How do I fix the problem?
Implement an assignment operator?
MyClass actually has pointers, and MYSQL_STMT*, I wonder how should I deal with MYSQL_STMT* variable.
I just need MyClassVar(3) object not the MyClassVar() which was first created when ClientClass object was created.
I came across this situation fairly often, and wonder if there's a good way to do it.
#include <stdio.h>
class MyClass
{
public:
MyClass() { printf("MyClass %p\n", this); }
MyClass(int a) { printf("Myclass(int) %p\n", this); }
~MyClass() { printf("~MyClass %p\n", this); }
private:
int mA;
};
class ClientClass
{
public:
void Foo()
{
printf("before &myClassVar : %p\n", &myClassVar);
myClassVar = MyClass(3); // this is the important line
printf("after &myClassVar : %p\n", &myClassVar);
}
private:
MyClass myClassVar;
};
int main()
{
ClientClass c;
c.Foo();
return 0;
}
MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0
Here's how the critical line breaks down:
myClassVar = MyClass(3);
First, MyClass(3) calls constructor and returns the object.
Second, myClassVar = copies the object to myClassVar.
Then the statement ends. The object (which is an immediate) is dead, and thus the destructor is invoked.
EDIT :
As for how to get around this. The only way I can think of is to use a placement new. I'm not sure if there's a better solution other than making a "set" method.
myClassVar = MyClass(3);
myClassVar continues to exist after this line. The lifetime of MyClass(3) ends at the semicolon.
As the other posts mentioned the object with the custom constructor MyClass(3) gets destroyed after the assignment operation myClassVar = MyClass(3). In this case you do not need a custom assignment operator because the compiler generated one copies the member mA to the already existing object myClassVar.
However since MyClass defines its own destructor you should adhere to the rule of three, which mandates that in such a case you should implement a custom assignment operator as well.
Responding to your edit: how do you fix what problem? It's not clear
what the problem is. If your class needs a destructor (and there's no
polymorphism in play), it probably needs both an assignment operator and
a copy constructor. Similarly, when "tracking" construcctions and
destructions, you should probably provide both as well, since they will
be called.
Otherwise: if the problem is that you're constructing and then
assigning, rather than constructing with the correct value immediately,
the simple answer is "don't do it". The compiler does what you tell it
to. If you write:
MyClass var;
var = MyClass(3);
you have default construction, followed by the construction of a
temporary, assignment, and the destruction of the temporary. If you
write:
MyClass var(3);
or
MyClass var = 3;
you only have one construction. (Note that despite appearances, there
is no assignment in the last snippet. Only construction.)
For class members, this difference appears in the way you write the
constructor:
ClientClass::ClientClass() { var = MyClass(3); }
is default construction, followed by creation, assignment and
destruction of a temporary;
ClientClass::ClientClass() : var( 3 ) {}
is just construction with the correct value. (Rather obviously, this
second form is preferred.)