Avoid creating object based on constructor value c++ - c++

My code is auto generated during compile time, so I don't know which object will be created.
During run time I have to decide whether I need it or not,so I want to creating object only if some condition satisfied, otherwise don't create and object below is example
class A {
public:
A(int type, int value):
type_(type),value_(value) {
if (type_ == 0) {
/*Create an object of this class and put in array */
} else {
/*Don't create an object of this class*/
}
}
private:
int type_;
int value_;
}
A a1(0,100); // Create an object
A a2(1,200); // Don't create an object
A a3(0,300); // Create an object
int main()
{
....
....
// use the object that was create and present in array
}

Inside the constructors body it's too late, the instance is already created then.
Either throw an exception, or use a template and sfinae to apply the restrictions at compile time.
Even better outsource the instances creation to a separate factory class, that acts on the condition. It can return a nullptr or otherwise empty smart pointer, to indicate the instance wasn't created.

The only way you can create this is from a static function. I would never use it like that, but if you really need it, you can do something like this.
class A {
public:
static A* createAnObject(int type, int value)
{
if (type == 0)
return new A(type, value);
else
return NULL;
}
~A();
private:
//Put constructur here so that will force programer to use your static function
A(int type, int value):type_(type),value_(value){};
int type_;
int value_;
}
};
A* a1 = A::createAnObject(0,100); // Create an object
A* a2 = A::createAnObject(1,200); // Don't create an object
A* a3 = A::createAnObject(0,300); // Create an object
int main()
{
//Now you need always to verify if you pointer is not NULL before use it
if(a1)
a1->somefunction();
....
}
But I do not recommend this way, creating object with new force you to always delete them by yourself and if you are a new programmer sometimes you will forget that, and if you have a NULL pointer so sometimes you will not verify it and try to call a function and this will crash you application.

Related

error: 'new' cannot appear in a constant-expression

class A
{
int data;
public:
void display()
{
cout<<"Value is "<<data;
}
void set_data(int x)
{
this->data = x;
}
A object = new A();
};
When I run the above code, I get the error stating "new cannot appear in constant expression". Why is it so?
Operator new returns a pointer but A is not a pointer type. You want A*:
A* object = new A();
You also want to move the above statement outside your class body and place it into appropriate function such as main():
int main() {
A* p = new A();
// do work
delete p;
}
That being said you either don't need a pointer at all and you can simply use an object with automatic storage duration:
A object;
Or you want to consider using a smart pointer such as std::unique_ptr:
std::unique_ptr<A> p = std::make_unique<A>();
class A
{
public:
A * object = new A(); // In any case not: "A object = new A();"
};
Or:
class A
{
public:
A object;
};
-
See (let's assume, for a moment, that you don't get the error), in both cases, on the first construction of A object, it creates another A object as a data-member. This A data-member (let's call it object.object ) creates in its turn another A as its data-member (let's call it object.object.object), and so to infinity (or until no more memory). I mean, as a data-member, it can't be either as A* object = new A();, or as A object;
-
I am not sure what was your intention, but if you want to link one A-object to another A-object, the class should be something like that:
class A
{
public:
A * object = nullptr
};
you have to make object of class A into main().
void main(){
A object;
}
First of all, you cannot create an object in the class declaration. Class declaration is like a blue print of the class. It is to say these are the components of my class - variables and member functions. You cannot instantiate anything inside it as no memory is allocated during this stage.
Note that you can instantiate an object inside one of the member function including constructor. These are called during object creation when memory is allocated.
Even if you use this statement inside a constructor you will go into an infinite loop as the constructor calls its constructor and so on until you have memory overflow.
You can declare the object in main like this:
int main() {
A obj = new A();
//other operations
} //Object A is destroyed once you come out of main.
Or dynamically like this
int main() {
A* obj = new A(); //dynamic allocation
//other operations
delete obj; //explicitly destroy
}

Deleting instantiated objects outside of a function?

How do you delete an instantiated object inside a function then delete when another function is called?
For example:
int function_test(){
object* a = new object();
}
int function_test2(){
delete a;
}
Object a needs to be deleted when function_test2() is called. Function_test() creates and sets the value of object a.
In order to delete something, you need a pointer to something.
When you allocate an object in function function_test and want to delete it in function_test2 you need to take care of a way for function_test2 to get a hold of the pointer to the object you wish to delete.
There are multiple ways of doing that, but the most common one is for function_test to return the pointer to the caller, and then passing that pointer to function_test2:
object* function_test() {
object* a = new object();
...
return a;
}
void function_test2(object* a) {
...
delete a;
}
The caller would need to "transfer" the pointer, like this:
object obj = function_test();
...
function_test2(obj);
Other ways of transferring the pointer are using file-static pointers, using global pointers, and using instance variables when functions function_test and function_test2 are member functions of a class.
You can't transfer local variables between functions. If you like to do something like this, I suggest you return the pointer, so you can pass it to the next function.
object *function_test()
{
auto *o = new object{};
return o;
}
however, this has as disadvantage that you have to capture this variable everywhere where you call it and have to to do memory management. Most likely you just want to use something object oriented, similar to:
class ObjectOwner final
{
public:
int function_test(){
a = new object();
}
int function_test2(){
delete a;
}
private:
object *a{nullptr};
};
which can be used as:
ObjectOwner owner;
owner.function_test();
owner.function_test2();
Even better would be using a std::unique_ptr<object> so that when you forget to call the 2nd function, the memory is freed.
Finally, you can consider using a constructor/destructor.
class ObjectOwner final
{
public:
ObjectOwner()
: a(std::make_unique<object>())
{
}
~ObjectOwner() = default;
void func() { /*Do something with a*/ }
private:
std::unique_ptr<object> a{};
};
Allowing you to write:
ObjectOwner owner{};
owner.func();

C++ static factory constructor

I am in the process of making a simulation and it requires the creation of multiple, rather similar models. My idea is to have a class called Model and use static factory methods to construct a model. For example; Model::createTriangle or Model::createFromFile. I took this idea from previous java code and was looking for ways to implement this in C++.
Here is what I came up with so far:
#include <iostream>
class Object {
int id;
public:
void print() { std::cout << id << std::endl; }
static Object &createWithID(int id) {
Object *obj = new Object();
obj->id = id;
return *obj;
}
};
int main() {
Object obj = Object::createWithID(3);
obj.print();
return 0;
}
Some questions about this:
Is this an accepted and clean way of making objects?
Does the returned reference always ensure correct removal of the object?
Is there any way to do this without pointers?
Just for the record, here's how this program might look like in proper C++:
class Object
{
int id;
// private constructor, not for general use
explicit Object(int i) : id(i) { }
public:
static Object createWithID(int id)
{
return Object(id);
}
};
int main()
{
Object obj1 = Object::createWithID(1);
auto obj2 = Object::createWithID(2); // DRY
// return 0 is implied
}
This is probably not what people would generally call a "factory", since factories typically involve some dynamic type selection. The term "named constructor" is sometimes used, though, to refer to the static member function that returns an instance of the class.
Your code currently contains a memory leak: any object created using new, must be cleaned up using delete. The createWithID method should preferably not use new at all and look something like this:
static Object createWithID(int id)
{
Object obj;
obj.id = id;
return obj;
}
This appears to require an additional copy of the object, but in reality return value optimization will typically cause this copy to be optimized away.
Is this an accepted and clean way of making objects?
It is (unfortunately) accepted but it's not clean.
Instead of factory functions just use constructors.
That's what they're for.
Does the returned reference always ensure correct removal of the object?
The reference is irrelevant except to the extent that it misleads users of the function.
In your example the reference has apparently misled yourself into not destroying the dynamically allocated object, but just copying it.
Better return a smart pointer.
But as already mentioned, it's even better to ditch the idea of factory functions.
They're wholly unnecessary here.
Is there any way to do this without pointers?
No, not if "this" refers to the dynamic allocation, but you can and should use constructors instead of factory functions.
Example:
#include <iostream>
namespace better {
using std::ostream;
class Object
{
public:
auto id() const -> int { return id_; }
explicit Object( int const id): id_( id ) {}
private:
int id_;
};
auto operator<<( ostream& stream, Object const& o )
-> ostream&
{ return (stream << o.id()); }
} // namespace better
auto main()
-> int
{
using namespace std;
cout << better::Object( 3 ) << endl;
}
By calling Object *obj = new Object(); you do allocate memory on the heap. In the lines following that statement you do return the reference to that object. So far, so good, but you do never delete the object you created to actually free the memory. By calling the function several times you will run in a memory leak.
There are two possible workarounds:
static Object createWithID(int id); would return a copy of the Object you create, so it would be enough to allocate it on the stack using
Object tmp;
tmp.id = id;
use c++11 smart pointer to let them handle the memory.
#include <memory>
static std::unique_ptr<Object> createWithID(int id)
{
std::unique_ptr<Object> tmp(new Object());
tmp->id = id;
return std::move(tmp);
}
This is an absolutely terrible way to create your objects. Every time that createWithID is called, a new Object is constructed on the free store which is never able to be destroyed.
You should rewrite createWithID to:
static Object createWithID(int id) {
Object obj;
obj.id = id;
return obj;
}
Or better, you could just supply a constructor for your Object objects.
If you want to enable polymorphic objects, you should use something like wheels::value_ptr.
Unless you are using polymorphism there is no reason for your factory functions to return any kind of pointer, they can just return the object by value. Any modern compiler will do return value optimization so there is no copy.
If you are after an "accepted and clean" way then that sounds quite opinion based and dependent on how this class will be used but what I would do is keep the definition of Model as small as possible. Only include what is needed for it to do its job with a minimum number of constructors required for normal usage:
namespace Simulation {
class Model {
private:
int id_;
public:
explicit Model(int id) : id_(id) {}
// minimum required to do the job...
};
}
Then, I would define the functions to create various flavors of Model separately. For example, as non-member, non-friend functions in a namespace:
namespace Simulation {
Model createTriangle(int id) {
Model model(id);
// do whatever you need to do to make it a triangle...
return model;
}
Model createSquare(int id) {
Model model(id);
// do whatever you need to do to make it a square...
return model;
}
}
That way, if you find you need another flavor of Model, you don't need to change the Model class. Your create functions can even be spread across multiple files if needed or become part of a Builder or Factory class. Usage would look like:
int main() {
Simulation::Model m1(0);
Simulation::Model m2 = Simulation::createTriangle(1);
Simulation::Model m3 = Simulation::createSquare(2);
}

How do I prevent the creation of temporary objects?

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?

Returning object as null returns what?

I have a class and a function that returns an object of that class, if i return NULL what exactly gets returned?
Example:
class someclass {
int a;
int b;
someclass::someclass(int a, int b) {
this->a = a; this->b = b;
}
};
someclass functionname() {
return NULL;
}
someclass foo = functionname();
Since I dont have a default constructor for the class what gets returned? Is it an actual usable object? Or just gibberish? Why cant I check like this?
if (foo == NULL) {
something
}
In C++, there is no actual null (however there is nullptr since new versions).
This means that NULL is defined like that:
#define NULL 0
So that it has the same qualities as 0, number variable, has. That's why you can't set your class to 0.
Compiler won't accept this code. C++ unlike Java and C# does not treat class instances as pointers (or references). So, for this return it will try to create new instance of someclass with the code someclass(NULL). Since you have no appropriate constructor, an error will occur.
If you want to have some "absent" values for the class, either program it inside class (for example, as boolean flag) or use pointers, for example:
someclass* functionname() {
if( ??? ) {
return new someclass(2,3);
}
else {
return NULL;
}
}
remember that C++ does not have grabage collector, so you will need to delete newed object yourself when not needed.
someclass *a;
a = functionname();
...
delete a;
forgetting this is most annoying error in C++.
The example is more of a situational description than something that should actually compile hence i didn't bother verifying it since it has nothing to do with the answer anyway and i doubt anybody would be interested in sifting through 100 lines of me defining a class and a function.
Anyway the answer is that if the class has any constructors that take 1 variable (optionally or otherwise) it will use that constructor and initialize the object with 0 in the first variable it can fit into