Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
In some code I have been working on, I am passing pointers into classes that aren't necessarily managed specifically by the class to which they are passed. If the class is destroyed then I check to see if the pointer's memory has or has not already been deallocated. The problem I have is that, if a pointer is deallocated and set to NULL before the class's destructor is called then I end up with a dangling pointer. The class ends up seeing the pointer is still non-NULL and tries to delete it which causes a segmentation fault. The best solution I could think of for this is to store the pointer by reference as shown below:
class PtrReferenceClass {
public:
PtrReferenceClass(int*& i_) : i(i_) {}
void run() {
if(i == NULL)
cout << "pointer is null\n";
else
cout << "pointer isn't null\n";
}
int*& i;
};
int main() {
int* i = new int(5);
PtrReferenceClass test(i);
test.run();
delete i;
i = NULL;
test.run();
return 0;
}
As expected, the output is:
pointer isn't null
pointer is null
Ofcourse when the pointer isn't store by reference I end up with a dangling pointer.
My question is as to whether or not this is generally considered to be a good programming practice. Are there any drawbacks to this solution or is there a better convention?
It depends upon what you are trying to accomplish.
If you want the memory around for your class use C++11's std::shared_ptr everywhere instead of an int*.
If you don't need the memory around for your class use C++11's std::weak_ptr.
As far as holding onto pointers in a class, that's not bad if they're wrapped in one of C++'s pointer wrappers. You can just hang onto raw pointers, but in general you should only do that if speed is an extreme concern.
You could check for NULLness in the destructor of PtrReferenceClass. A much better alternative whould be to use a shared_ptr or really clarify ownership of i.
Agree with #Paranaix in main thread comment, as well as #ToniBig, I can't really think of a situation where you would need this. Such a thing is probably to protect against horrible programmer error. You should also keep in mind that you are storing a reference to the pointer i, and that reference will be left dangling when the pointer i goes out of scope, regardless of whether the memory i refers to has been deallocated or not. SO in conclusion, please don't do this.
All you've done is trade one lifetime problem for another. The new problem may be easier to solve... or it may not.
Now you can detect that the object is gone... as long as something has kept the pointer variable alive.
Think carefully about your variable lifetimes, and whether a reference-to-pointer (or equivalently, pointer to pointer) makes sense should become clear.
There certainly are cases where double indirection is valuable. I will leave you with a quote: "Any problem in computer science can be solved by adding another layer of indirection"
These are options :
give ownership to class and manage lifecycle inside it.plus with safe
setter method for changing it when you want. Again do it if you have to create or obtain that pointer outside,otherwise just do all inside.
only pass that pointer to methods that will use it and when
needed.void run(int* i).
Related
This question already has answers here:
How do I pass smart pointers into functions?
(4 answers)
Should/Can smart pointers be passed by reference in functions
(2 answers)
Whether to pass shared pointer or raw pointer to a function
(2 answers)
Passing the address of dereferenced smart pointers to functions that expect raw pointers
(4 answers)
When should I use raw pointers over smart pointers?
(8 answers)
Closed 11 months ago.
I am trying to refactor some oldish code, and I want to use unique_ptrs for some objects where they are clearly suited. Up till now, shared_ptrs have been generally used.
Given that for most intents and purposes both smart pointers behave identically, in many cases I don't see why I should have to distinguish between the two. So to make a trivial example:
EDIT: I've had to make the object a little less trivial...
class NamedItem
{
string name;
string& GetName();
}
class SessionObject: public NamedItem
{}
class TrivialObject: public NamedItem
{}
class NameCacher:
{
vector<??????<NamedItem>> named_items;
void AddNamedItem(??????<NamedItem>& named_item)
{
named_items.push_back(named_item);
}
void PrintAllNamedItems()
{
// Print all names
}
}
unique_ptr<SessionObject> session(new SessionObject("the session"));
shared_ptr<TrivialObject> some_object(new TrivialObject("whatever"));
NameCacher names();
names.AddNamedItem(session); // The session pointer will not delete the session object, even if names stops referencing it.
names.AddNamedItem(some_object); // The some_object pointer is welcome to delete itself if names stops referencing it and nothing else is.
names.PrintAllNamedItems();
// If some_object goes out of scope, then its shared_ptr will delete it at this point.
Given that 80% of the day-to-day behaviour of the smart pointers is the same, isn't there a way to do this? The only thing I've found is to convert a unique_ptr to a shared_ptr - which is categorically not what I want to do. Ideally, I'd like the base class of the two smart pointers - but I can't find one.
Many thanks to all those who have responded to my question. I've been speaking with a knowledgeable colleague as well, and it's taken us about an hour to get a common understanding of the whole situation - so my apologies for not being able to convey this in my simplified example.
I thought I'd add this as an answer to explain to future readers why the premise of my question was ill-conceived. This attempts to summarise some of the comments on the original question.
I believe that I had misunderstood the utility of unique_ptrs, and had been using them incorrectly. What I had originally wanted was a pointer that behaved as a shared_ptr does, but did not need to manage its reference count - because I could guarantee that it would stay alive for the entire session. As such, the code which referenced it could treat it the same as a normal shared pointer - it is just didn't need to increment or decrement the reference count.
However, the purpose of a unique_ptr is that it's ownership can be transferred - and in my example above I am attempting to send it to another object while not transferring its ownership. As several commenters pointed out, this could be done much better by dereferencing it as a raw pointer or a reference as it is given to the recipient - but this would be a very different intention to when a shared_ptr is provided. As such, they shouldn't have a common interface as I had originally asked.
My thanks again for everyone who helped me understand my mistake.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I might have some aspects of this wrong, this is really the first time I have dealt much with shared pointers in particular.
I am working on traversing a tree. My tree consists of a linked list, with a vector of shared pointers representing all children for each node. To traverse, I am (to begin with) trying to do this:
//--------------------------------------------------------------
void setupMesh(){
Mesh mesh;
shared_ptr<Mesh> shared_mesh(&mesh);
meshes.push_back(shared_mesh);
checkChildren(root, &temp_mesh);
}
//--------------------------------------------------------------
void checkChildren(Node * temp_node, Mesh * temp_mesh){
if(!temp_node->children.empty()){
for(int i = 0; i < temp_node->children.size(); i++){
if(i > 0){
shared_ptr<Mesh> new_mesh(new Mesh);
meshes.push_back(new_mesh);
}
temp_node = temp_node->children[0].get();
checkChildren(temp_child, temp_mesh);
}
}
}
My tree structure itself seems fine, but it's more an issue with how I'm traversing it, and how I'm keeping track of pointers. It is currently returning bad access errors. From what I can tell, it looks like I am inserting a pointer to a temporary object, temp_node, and temp_mesh.
To simplify the process I had in mind:
Loop through all children that belong to node[0] (root).
For each of the children, perform this same loop on them. If the child is child[0], continue adding it's coordinates to the same temp_mesh object, but if it is another child, create a new mesh to store it, and all first children of it.
Any new meshes should have a pointer pushed back into the meshes vector (vector>).
Does anyone have advice on how I could do this more efficiently, or where I'm going wrong with handling these pointers in memory.
It is currently returning bad access errors.
Then that's what you should worry about as your first priority. That's a serious bug.
From what I can tell, it looks like I am inserting a pointer to a temporary object, temp_node, and temp_mesh.
This aren't "temporary" objects, that means something different (why do you keep using "temp" in your variable names?), but you're right about the problem:
shared_ptr<ofMesh> shared_mesh(&temp_mesh);
This creates a shared_ptr which owns the pointer &temp_mesh and so will delete it when there are no more shared_ptr objects that share ownership of that pointer.
But that pointer is the address of an automatic variable (aka stack variable) which goes out of scope at the end of the block. You don't "own" that object, the block scope of that function manages it automatically. If you don't own it then you can't give ownership of it to the shared_ptr, because it's not yours to give away.
When the scope ends the automatic variable temp_mesh will be destroyed automatically, but there are still shared_ptr objects that hold that pointer, thinking they own it. When you try to access the object through those shared_ptr objects you access a destroyed object, after its lifetime has ended. Then when there are no more shared_ptr objects that own the pointer it will be deleted, but it wasn't created with new so that's a serious bug. (You get this right in the other function, so I'm not sure why you've done it wrong in setupMesh).
If you want a shared_ptr to own an object you need to create it with new, or preferably create it with std::make_shared: *
shared_ptr<ofMesh> mesh = std::make_shared<ofMesh>();
mesh0->setMode(OF_PRIMITIVE_LINE_STRIP);
mesh->setupIndicesAuto();
mesh->addVertex(root->location);
mesh->addColor(ofColor(0));
meshes.push_back(shared_mesh);
checkChildren(root, mesh.get());
This creates an object that is owned by a shared_ptr right away, so there's no problem of transferring ownership of something that can't be owned by a shared_ptr.
* Or you can use a "null deleter" but that's way too advanced for this answer, and won't make it OK to use automatic variables like this.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Is it useful to create a pointer or an array of pointers on the heap ? if so when and why would I need to do so ?
For example:
#include <iostream>
class Box { /* things... */ };
int main(void){
// Single pointer on the heap
Box** pBox = new Box*(nullptr);
*pBox = new Box();
// Array of pointers on the heap
Box** pBoxes = new Box*[3]{};
pBoxes[0] = new Box();
pBoxes[1] = new Box();
pBoxes[2] = new Box();
// Delete pointers...
return 0;
}
EDIT: Just to make my question more clear ... I know dealing with raw pointers is not the best practice ... I just want to fully understand pointers and their uses as they are important part of c++ hence my question is (is it useful...).
The reasoning behind allocating any memory space on the heap or on the stack is not related to the type of variables allocated, it's related to how it's allocated and how it's meant to be used.
In any case, nowadays you should usually avoid new statements and use "managed" pointers, particularly the std::xxx variants.
From what i read, the heap has slower access speed than the stack so, I don't think that it is very useful to do what you are talking about.
Maybe this will help you trought your research: http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html
As another answer mentioned, usually actual access to the heap is slower than access to the stack, however access speed generally isn't the reason for creating and dealing with pointers.
The typical use case for pointers is to avoid copying data. When you're dealing with large objects and passing them between many functions, it is considered "better" to pass by reference rather than by value.
If you use the object from the stack (unless you pass it as a reference, but there are limitations when doing this) it makes a copy of the whole thing for the called method. When passing a pointer to a method, it is only copying an address.
See if this article helps you understand the differences.
Yes, there can be reasons to have pointers on the heap. A factory function that keeps track of every object it creates might store them in a vector, for example:
vector<unique_ptr<Box>> BoxFactory::allBoxes;
Box* BoxFactory::makeBox()
{
allBoxes.emplace_back(make_unique<Box>());
return allBoxes.back().get();
}
Note: some people have suggested that this is not double-indirection. It is:
// Accesses some_box_member of the first Box.
allBoxes.data()->get()->some_box_member
Just as with the OP's example, you have two pointers in play, not just one. The vector contains pointers which have been allocated on the heap, and those pointers contain another pointer that points to the Box object.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have two classes. One that creates a resource, which is then sent to the other class which stores it for access by different parts of the program. What I do is:
typedef std::shared_ptr<Object> ObjectPtr;
ObjectPtr CreatorClass::Create()
{
ObjectPtr(new Object);
// ...
return ObjectPtr;
}
void StorageClass::Store(ObjectPtr obj)
{
myVector.push_back(obj);
}
ObjectPtr StorageClass::Get(int index)
{
return myVector[index];
}
My questions are:
Am I correct in using shared_ptr or should I use something else?
Should I be passing ObjectPtr by value to Store function and from Get function?
Am I correct in using shared_ptr or should I use something else?
You are correct if you need shared ownership. Otherwise you are wrong.
Should I be passing ObjectPtr by value to Store function
Yes. Although you could still do .push_back(std::move(obj)) to avoid a needless copy.
and from Get function?
Depends on whether you want to
modify the original shared_ptr in the vector, then return by non-const reference,
just observe it, then return by const reference
none of the above, i.e. get you own copy of it, then return by value.
Well, generally speaking, you are not doing it very efficiently. I see multiple issues with the code, almost close to antipattern.
Omnipresent Creators. My gosh, I hate them. What's the point of a
'creator' in your example? Why can't the object be created by the
user directly?
Store function. It has two issues. First it does nothing apart putting an element to the vector, coupled with sister get, which
simply extracts. Given that, those two functions should be sent to
meet their Creator (pun intended). Instead, myVector should be
exposed to class users. Otherwise, you are severely limiting user
experience (for instance, how would they even know if they can call
get with given index? They don't know the size of the vector!). Avoid
getters and setters.
Second issue with Store - if we imagine that Store does more than simply pushing stuff to vector, and thus it's existence is justified,
it accepts shared pointer by value. Which means, you are atomically
incrementing the counter. Performance weeps. Pass shared pointer by
reference to reduce the impact. Better yet, do not use shared
ponters. There usage is not justified in 99% cases I've seen.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I know the difference between the points-to (->) and dot (.) operator but I don't see why the need for the two arrises? Isn't it always just as easy not to use pointers and just use the dot operator? From http://www.programcreek.com/2011/01/an-example-of-c-dot-and-arrow-usage/
#include <iostream>
using namespace std;
class Car
{
public:
int number;
void Create()
{
cout << "Car created, number is: " << number << "\n" ;
}
};
int main() {
Car x;
// declares x to be a Car object value,
// initialized using the default constructor
// this very different with Java syntax Car x = new Car();
x.number = 123;
x.Create();
Car *y; // declare y as a pointer which points to a Car object
y = &x; // assign x's address to the pointer y
(*y).Create(); // *y is object
y->Create();
y->number = 456; // this is equal to (*y).number = 456;
y->Create();
}
Why ever bother using pointers? Just create Y as X was, it would work the same. If you say you need pointers for dynamically alocated memory, then why bother having the dot operator?
I think you're mixing two separate concerns.
First, the -> operator is unnecessary, yes. x->y is equivalent to (*x).y, but the -> operator is easier to type, so it's basically just a convenience.
The second part is whether to use pointers at all.
And you're right, often you shouldn't. By default, just create your objects then and there, and refer to them direclty:
Foo bar;
bar.baz():
but pointers are still necessary for a lot of cases. Objects need to be able to reference other objects. A reference can do that, but it can't be reseated. Once it is initialized, it will always point to the same object.
A pointer can be updated to point to a different object.
Linked lists, tree data structures and countless other things depend on objects being able to point to other objects.
So yes, we need pointers. But we don't need the -> operator. We just use it because it's convenient.
a. it just makes it easier to semantically understand the code without looking at the types, or having special notations like m_pszMyName. You can instantly tell reading the code what is a pointer and what is a value.
b. Think of the case of shared_ptr and overriding operators. shared_ptr<T>->get() means something else than shared_ptr<T>.get(). The first being the function in a pointed object, the second one being the function of the shared_ptr class itself. This is just one example, but you see the point.
From your link:
The following example should be a good one.
It is actually a bit confusing. Why would you ever create an object on the stack (Car x;) and then create a pointer to it to access it using ->?
Instead of trying to answer the implied question "Why do we need pointers?" I'll try to clear up any confusion that might have arisen from that example.
In your comment you say:
I'm wondering if there's a difference between objects that are created differently.
In the example there is only one object, the Car on the stack created by Car x; (to be complete there is also a Car-pointer on the stack, created by Car *y;). They go out of scope when main() exits, so their memory gets cleaned up.
But there is another way to create objects, which I guess you already know about based on your comment, and this is to use new to initialize them on the heap: Car *z = new Car;. Objects on the heap will never go out of scope, so you can keep using them after the function that called new exited, but you have to explicitly clean them up using delete to prevent memory leaks.
So there it is, a more realistic use of a pointer to an object: the return value of new.
Isn't it always just as easy not to use pointers and just use the dot
operator?
C/C++ like other higher order languages do not encapsulate the pointers with some sugar coating syntax. Pointer's arise naturally and the list below is not exhaustive
Allocating memory from heap. Static data allocation, or allocating storage in stack is always not feasible. There are overheads with transfer of ownership, space constraint and dynamic nature of your program.
Reading and writing files.
Iterating over objects including C-Type string. You can use array access syntax, but there is little safety difference and arrays are degenerated to pointers when you pass to a function(size information is lost).
All the above can be encapsulated into objects when you thing from C++ perspective.
FILE IO through iotream
pointers through smart pointers(some from the C++98 and some in C++11 or eve boost)
Iterators for STL Type Objects.
Using reference
Nevertheless, Pointers are there even in languages where you don't see them explicitly. They are just encapsulated to higher order objects.
This explains to some extent why we can't think beyond pointers, the next part probably you are interested is in the syntax. Why do we atall need ptr->somemember instead of (*ptr).somemember.
Its just shorthand for a repetitive usage. C/C++ programmers have got used to it and I have not seen till to date a single program using the superfluous syntax.
-> is just for short. Consider a class represent nodes of trees:
struct node {
int data;
node* left;
node* right;
};
The member left is a pointer point to the left child of the node. Suppose we have a pointer to some node p, now we want to get the pointer point to the right child of the left child of the left child of p, using dot we have to write (*(*(*p).left).left).right, difficult to read and error-prone, using -> we can simply write p->left->left->right, very clear.
The existence of both -> and . operators in C++ is a direct influence from C. C makes the distinction between accessing an object through a pointer and accessing an object which is declared in the current scope.
In C++ references are a natural extension of accessing locally scoped objects.
I don't know whether the creators of C considered this, but I always used to use it as a small optimisation guide. Looking at a piece of code, you could see that -> would calculate the final address at runtime, whereas the . operator would calculate the address at compile time. This even works when accessing members of structures. Consider the following: myptr->mMember.mValue The offset from mMember to mValue can be calculated at compile time, whereas the final address calculation from the pointer must be calculated at run time. A minor consideration as far as optimisation is concerned these days, I'll admit, and with references in C++ it's no longer possible to do this, but 20 years ago it was something to bear in mind.
Yes, you could always use (*x).member instead of x->member, but would you really want to when x is a complex expression?
Having related things (* and . in this case) far away makes the source code less readable, so having the -> "in one place" is simply a nicer syntax.
As for the need for the concept of pointers, there are 2 main reasons:
1. Object Lifetime
There are two ways to allocate an object
On the stack.
In the dynamic memory.
The stack winds and unwinds as the flow of execution enters and exits functions, so the lifetime of a stack object is inevitably married to how long we stay in the function that created it.
If you need an object that lives longer than the function that created it, you need to create it in the dynamic memory, and the only way to identify such object is by its memory address, aka. pointer.
2. Object Sharing
Is there more than one other object that needs to access the object? If yes, then there is no way for these other objects to reference the shared object, other than holding its address.
Even if you have only one other object, but their lifetimes differ, the "lifetime" reason applies. If there is only one other object and their lifetimes match, than make it a field.