What I don't understand is what is the difference between using a pointer to a class and generating a new instance of it. It's just for performance? Here I made a class and made m the pointer to the class and n the instance of the class.
And another question: can i make a pointer the class and use another constructor? like myClass* p(7); p->afis(); ?
#include <iostream>
using namespace std;
class myClass
{
int a;
public:
myClass(void);
myClass(int);
void afis();
~myClass(void);
};
myClass::myClass(void)
{
a = 5;
}
myClass::myClass(int nr)
{
a = nr;
}
void myClass::afis()
{
cout << a;
}
myClass::~myClass()
{
}
int main()
{
myClass* m; //<--
m->afis();
myClass n(7); //<--
n.afis();
cin.get();
}
myClass* m;
is just an pointer to the type myClass it does not point to any valid object, dereferecing such a pointer is Undefined Behavior.
An Undefined Behavior means that your program is invalid and it may seem to work or it may crash or it may show any weird behavior, all safe bets are off. So just because your program works does not mean it is safe and it will always work.
To write a valid program you will have to make the pointer point to a valid object.
For example:
myClass obj;
myClass*m = &obj;
In the second case:
myClass n(7);
It creates an object n of the type myClass by calling the constructor of myClass which takes one argument of the type int.
This is a valid way of creating an object.
can i make a pointer the class and use another constructor
Making a pointer doesn't call a constructor. The pointer is uninitialized until you set it to the address of some object (maybe a brand new object created with new).
myClass* m; //<--
m->afis();
This is undefined behavior, you have a wild pointer because m hasn't been initialized.
Better:
std::unique_ptr<myClass> m(new myClass(constructor, args, here));
m->afis();
Related
extern class objx;
class Someclass
{
public:
Someclass();
void bar(objx);
objx &om;
};
void foo()
{
Someclass c;
objx o;
c.bar(o);
}
void Someclass::bar(objx& op)
{
//Save op in some local privatefield for later use
om = op; //Here there should not be a copy;
}
Above code is wrong right? Because when o goes out of scope in foo() it is destructed. Is there a way not to copy o into a new object in bar? For example using bar(objx&& op) so we don't have to copy object or use smart pointers and for sure avoiding new/delete? And when bar() returns op would go out of scope and object gets destroyed.
[EDIT]
I could use a pointer instead. But the caller should keep track of the lifetime of the object. That is what I want to avoid.
[EDIT2]
The question is this: Is there a mechanism to keep a local variable alive as long as its reference is passed by reference to other functions (scopes)?
[EDIT4]
This code achieves same functionality using pointers:
#include <sstream>
class Someclass
{
public:
Someclass() { }
void bar(std::stringstream *);
std::stringstream *om;
};
void Someclass::bar(std::stringstream* op)
{
om = op;
}
int main()
{
Someclass c;
std::stringstream o;
c.bar(&o);
return 0;
}
Above code is wrong right? Because when o goes out of scope in foo() it is destructed.
It depends on what "Save op in some local privatefield for later use" means. Making a copy is correct. Referring to the object would not be.
Is there a way not to copy o into a new object in bar?
You can move into a new object instead.
The receiver class is already instantiated.
Option 1: Don't do that.
Option 2: Assign the value member.
From the responses you kindly provided I concluded that it can be done if the passing object has the move semantics implemented in it.
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
}
Base abstract class:
class Satellite
{
public:
Satellite();
virtual void center()=0;
virtual ~Satellite(){}
};
First derived class
class Comm_sat:public Satellite
{
public:
Comm_sat();
void center() override{cout << "comm satellite override\n";}
};
Second derived class
class Space_station:public Satellite
{
public:
Space_station();
void center() override{cout << "space station override\n";}
};
Pointer version of the functions
void f(Satellite* ms){
ms->center();
delete ms;
}
int main()
{
Comm_sat* cs = new Comm_sat;
Space_station* ss = new Space_station;
f(cs);
f(ss);
}
The objects created using new in main() are properly destroyed in f(), right?
Reference version of the functions
void f(Satellite& ms){
ms.center();
}
int main()
{
Comm_sat cs;
Space_station ss;
f(cs);
f(ss);
}
Is the reference version better?
Besides, I try to use unique_ptr, however, I get errors
void f(Satellite* ms){
ms->center();
}
int main()
{
unique_ptr<Comm_sat> cs{new Comm_sat};
unique_ptr<Space_station> ss{new Space_station};
f(cs);
f(ss);
}
Error: cannot convert std::unique_ptr<Comm_sat> to Satellite* for argument 1 to void f(Satellite*)
Error: type class std::unique_ptr<Comm_sat> argument given to delete, expected pointer delete cs;
Same error for the other derived class.
Is the reference version better?
Yes, although a better way to put this would be "the pointer version is worse". The problem with the pointer version is that you pass it a valid pointer, and get a dangling pointer when the function returns. This is not intuitive, and leads to maintenance headaches when someone modifies your code thinking that you have forgotten to delete cs and ss in the main, not realizing that f deletes its argument.
The version that uses a reference is much better in this respect, because the resources are managed automatically for you. Readers of your code do not need to track the place where the memory of cs and ss gets released, because the allocation and release happen automatically.
I try to use unique_ptr, however, I get errors
There is no implicit conversion from std::unique_ptr<T> to T*. You need to call get() if you want to pass a raw pointer:
f(cs.get());
f(ss.get());
The objects created using new in main() are properly destroyed in f(), right?
They're destroyed, and cleaned up correctly, yes. "Properly" is a stretch though, since all this manual-new-and-delete-raw-pointers stuff is poor style.
The reason unique_ptr isn't working for you is that ... it's a unique_ptr, not a raw pointer. You can't just pass it as a raw pointer.
Try
void f(Satellite* ms){
ms->center();
}
// ...
f(cs.get());
or better, unless you really need to pass nullptr sometimes,
void f(Satellite& ms){
ms.center();
}
// ...
f(*cs);
or best of all, since you don't show any reason to require dynamic allocation at all:
void f(Satellite& ms);
// ...
{
Comm_sat cs;
f(cs);
} // no new, no delete, cs goes out of scope here
so I have a question about passing by reference. I tried passing an object to a member function by reference and have that member function call another member function with the reference I passed as an argument. However, the compiler says that the member function invoked is not found. Why is that so? The code below will describe my frustration in ways my words cannot express themself
// CODE 1
class someClass {
int data;
public:
someClass(someClass&);
someClass someFunction(const someClass&)
};
someClass::someClass(someClass &obj) {
data = obj.data;
}
someClass someClass::someFunction(const someClass &obj) {
someClass demo(obj); // <- this doesn't work
someClass demo(&obj); // <- neither does this
someClass demo(*obj); // <- or this
someClass demo2(*this); // <- this works though
}
Having a hard time understanding this, it may seem trivial but I do appreciate all the help I may get. Also, something mysterious has happened in xcode, when I tried the following (referring to CODE 2), it works. Any idea why?
// CODE 2
class someClass {
int data;
public:
someClass(someClass&);
void setData(int x) { data = x; }
};
int main() {
someClass first;
setData(10);
someClass second;
second = first;
//Mysteriously, it worked without overloading the '=' operator. Why?
//Also, I mentioned XCode just in case someone might say it's compiler specific
return 0;
}
The difficulties appear to be as follows:
someClass demo(obj);
You are trying to pass a const reference to a function that requires a reference that is not const. The typical pattern is to have a copy constructor take a const reference parameter, which avoids this problem.
someClass demo(&obj);
In this case, the compiler is looking for a constructor that takes a pointer to a someClass, but cannot find it. &obj returns a pointer to obj, not a reference to obj.
someClass demo(*obj);
In this case, you are attempting to dereference obj as if it was a pointer, but it is a reference, not a pointer.
someClass demo2(*this);
This works because you are dereferencing the this pointer, which points at an instance of someClass.
I have a fairly simple question, but cannot wrap my head over it.
Consider I have this code:
#include <iostream>
#include <vector>
using namespace std;
class B
{
public:
B(const int& val) {this->val = val;}
int val;
};
class A
{
public:
A() {}
void Set(B& ptb)
{
ptBs.push_back(&ptb);
}
void Set(const int& val)
{
ptBs.push_back(new B(val));
}
std::vector<B*> ptBs;
};
int main()
{
A* ptA = new A();
ptA->Set(B(10));
ptA->Set(38);
for (int i=0; i<ptA->ptBs.size(); i++)
cout << ptA->ptBs[i]->val << endl;
delete ptA;
system("pause");
return 0;
}
The output result is:
10
38
But I think there is memory leak is going on in void Set(const int& val) if I won't call delete with array elements, created by this method.
How can I say, which elements of std::vector have been created on heap so I could free memory in ~A() destructor like this:
~A()
{
for (int i=0; i<ptBs.size(); i++)
delete ptBs[i];
}
And do I have to delete vector elements, created via temporary new operation call at all?
Probably I don't see something very simple here, but I really need this functionality in my application.
PS. 10 and 38 are just a simple example. Set function can be called thousands of times with different arguments.
Fortunately, this line won't compile:
ptA->Set(B(10));
This is because B(10) is a constructor cast expression which creates a prvalue temporary of type B; a prvalue cannot bind to the lvalue reference B & parameter to void A::Set(B& ptb). This is the C++ language protecting you from the consequences of storing a dangling pointer to a temporary value.
It usually makes more sense for A to store its B items by value:
std::vector<B> Bs;
You should decide on whether you give ownership of the object of type B to the instance of A or not. Mixing both will not lead to anything good. Just imagine documenting this class: this class may or may not take ownership to the objects it holds.
Alternative approach that I do not recommend is to create a wrapper to pointers to B, that takes a pointer to B and a boolean flag in it constructor and the boolean flag will indicate if the pointer is to an object allocated on the stack or to an object on the heap.