I'm just getting used to smart pointers using std::auto_ptr.
Assume that I want to call a function with both auto_ptr and normal Pointers.
auto_ptr<uint32> data_smart(new uint32[123])]);
uint32 data_fix[123];
uint32* data_dumb = new uint32[123];
processData(data_smart);
processData(data_fix);
processData(data_dumb);
What is the best practice for this without overloading? Having the processData function with a uint32* argument? Can I cast the smart pointer to uint32* for this case with .get()? Or what is the way I should do it?
Thanks in advance!
1.
auto_ptr<uint32> data_smart(new uint32[123])]);
Don't do that. auto_ptr works with scalars only (it calls delete rather than delete[]).
2.
auto_ptr owns the object it points to, so unless you want to pass the ownership to that function (in your code you don't), the function should accept a normal pointer. So you should change the call to:
processData(data_smart.get());
in order to explicitly express that data_smart continues to own the object.
EDIT: Noah Roberts' comment on your question is the bigger issue here, but this answers the question asked even if the example code is wrong....
... without overloading ...
If you want to do it without overloading, the only option that's going to work for all of these is to make the method take a dumb pointer parameter.
Can I cast the smart pointer to uint32* for this case?
No. Use std::auto_ptr<t>::get().
First of all, you don't initialize auto_ptr with a pointer to array. It's not supported, and you'll end up with memory leaks. std::auto_ptr handles only single objects.
If you still want to use std::auto_ptr, but for single objects only, you need to remember that std::auto_ptr transfers ownership in copy constructor. That means that your local auto_ptr (data_smart) won't hold any memory after you call processData if you pass data_smart by value.
In the end, you probably want to use boost::scoped_array or boost::shared_array.
Best practice is to not use auto_ptr. It will be deprecated in C++0x and replaced by std::unique_ptr (Reference: C++0x Draft Standard, Appendix D, Paragraph 10). In the meantime, alternatives include std::tr1::shared_ptr and boost::scoped_ptr.
But your example is an array, and those pointer types are not for arrays. You can use boost::shared_array for that.
However the Standard itself does not have array smart pointers. That’s probably because they believe you should be using std::vector instead (or std::array for fixed size arrays when you know the size at compile time). Given that, you could do the following:
std::vector<uint32> dataVector;
data.reserve(123);
// or, if the size is always 123:
std::tr1::array<uint32, 123> dataArray;
Now, you can call your function that accepts a regular plain-old uint32* because both vectors and std::tr1::arrays have methods to give you access to the data as a pointer to a C-style array:
processData(&dataVector[0]);
processData(dataArray.data());
I would strongly recommend adding bounds-checking if you are going to do this. Pass a second argument to processData with the size of the array:
processData(&dataVector[0], dataVector.size());
And if you can abandon C-style pointer/arrays entirely, a better way might be to pass by reference:
void processData(std::vector<uint32>& data) {
// process the data
}
// call it like this:
processData(dataVector);
But this only works for vectors, not std::tr1::arrays or any other container. So, taking it one step further, you could use a template that accepts iterators:
template <class AnIterator>
void processData(AnIterator begin, AnIterator end) {
for (AnIterator it = begin; it != end; ++it) {
// process each item
}
}
// call it like this
processData(dataVector.begin(), dataVector,end());
// or like this
processData(dataArray.begin(), dataArray.end());
// or even like this (assume c_data is a C-style array):
processData(c_data, c_data + number_of_items_in_c_data);
The last one works because pointers to C-style arrays can be used as iterators.
In your situation using a vector is the safest choice:
std::vector<uint32> data(123);
The signature of processData should ideally be:
void processData(const std::vector<uint32> & data);
However, this one is more frequently used:
void processData(uint32 * bytes, int length);
In both cases you can use the vector:
// 1
processData(data);
// 2
processData(data.data(), data.size());
Not withstanding why you should want to use auto and dumb (as you put it) pointers for the same data to the same name function without overloading, auto_ptr cannot be used on arrays because it calls the wrong sort of delete.
Have a look at this: http://learningcppisfun.blogspot.com/2007/05/custom-deleters-with-smart-pointers.html
Also have a look at this SO question regarding smart pointers to arrays: auto_ptr for arrays
It amuses me that the data_smart variable is the dumbest of the three. That is, when that scope ends, the auto_ptr destructor is going to call delete on its pointer and not delete[] which leads to UB (which is worse than the possible memory leak from data_dumb).
So, the point is don't use auto_ptr for arrays, use vector.
Onto the real question. First, if possible use reference arguments instead of pointer arguments. If this isn't possible use bare pointers and auto_ptr::get() gives access to the underlying pointer.
Ignoring the already HAMMERED don't use auto_ptr on array.
What is the best practice for this without overloading?
It appears your method will not take ownership, so the remaining question is will it be changed?
Having the processData function with a uint32* argument?
processData( uint32* ) Thats one option, but maybe not the best.
processData( uint32[123] ) if your not editing (123 is starting to push some copying).
processData( uint32 &[123] ) by ref and apply const as necessary.
Can I cast the smart pointer to uint32* for this case with .get()?
You can get the pointer content of the smart pointer using get(), it's already 'typed' so no need to cast it.
Aside:
Data and manipulation of at such a raw level should be in the one class, you probably don't even need to pass what should be a member variable into a member function.
Related
This question was discussed a few times but all those discussions almost a decade old and there was no good solution. The question is the same.
We have smart pointers, like unique_ptr, that is great. We have tons of C functions returning a pointer to an object as an argument which later needs to be released.
Let's say this is the function:
int CreateSomething(OBJECT_TYPE** pObject);
So, what would we normally do without smart pointers? Apparently something like that:
OBJECT_TYPE* pObject;
if(CreateSomething(&pObject) == 0) {
// Use the pObject pointer
delete pObject;
}
Now, I would like to rewrite it using smart pointers, and I would like it to be as simple as this:
unique_ptr<OBJECT_TYPE> pObject;
if(CreateSomething(&pObject) == 0) {
// Use the pObject pointer
}
Technically, that would be quite possible if unique_ptr would have T** operator&, and if it would count on this kind of workflow, but it doesn't.
In the case when we want to use a smart pointer here, we have to declare a regular pointer, use it in that function, and then reassign it to the smart pointer. But those extra steps can and should be eliminated, and I hope that maybe there is already an implementation which would allow me to do what I need in that simple manner as I showed.
Yes, I can write my own smart pointer or mediator, which would simplify the usage of unique_ptr, but first I'd like to ask if maybe there is already something implemented in the depth of standard libraries for this and I simply overlooked it?
C++23 has very recently added std::out_ptr for exactly this use case.
write a wrapper: (uncompiled code)
namespace smart_ptrs {
std::unique_ptr<OBJECT_TYPE> CreateSomething() {
OBJECT_TYPE *p = nullptr;
if (::CreateSomething(&p))
return std::unique_ptr<OBJECT_TYPE>(p);
return std::unique_ptr<OBJECT_TYPE>();
}
Then you can write:
std::unique_ptr<OBJECT_TYPE> ptr = smart_ptrs::CreateSomething();
if (ptr) {
// Use the pObject pointer
}
In the case when we want to use a smart pointer here, we have to declare a regular pointer, use it in that function, and then reassign it to the smart pointer.
Basically, yes. That is exactly what you must do (for now anyway, until std::out_ptr is added in C++23).
C++ smart pointers simply do not expose access to their held pointer, thus no way for you to obtain its address to pass to the C function. So, you have to use the smart pointer's constructor or assignment operator instead, which requires the object pointer to already be initialized first.
I'd like to ask if maybe there is already something implemented in the depth of standard libraries for this and I simply overlooked it?
You have not overlooked anything.
I used to allocate memory in my C++ project with new
char* buffer = new char [size];
...
delete[] buffer;
and I'd really like to move forward and use unique_ptr, like this
unique_ptr<char[]>buffer(new char[size]);
but then I use istream& get (char* s, streamsize n); which takes char* as a first argument, so what should I do? I've tried to cast types, but failed. I also know I can use vector<char> instead of pointers, but I don't really like to use it. Thank you!
The class std::unique_ptr has a method called get() to access the underlying pointer: use that.
unique_ptr<char[]> buffer(new char[size]);
...
myIstream.get(buffer.get(), n);
There is a std::unique_ptr<T[]> specialization for arrays. How to use it in your case in shown by Smeehey in his answer.
But, as of Scott Meyer's "Effective Modern C++" Item 18 (Emphasis mine):
The existence of std::unique_ptr for arrays should be of only intellectual interest to you, because std::array, std::vector, and std::string are virtually always better data structure choices than raw arrays.
So, use the classes that are made for this purpose instead of hacking your way there with std::unique_ptr.
One of the way is to use vector rather than unique_ptr, but using unique_ptr has it's own benefits.
I also faced the same issue earlier, in which I had a buffer allocated using unique_ptr and passed it as a argument to read function. The only way to get rid of this is using the get() method which converts the unique_ptr to char*.
Also make sure you have #include <memory> to avoid other errors which I faced.
Thanks!
I want to ask whether there are some problems with the copy for the vector of pointer items. Do I need to strcpy or memcpy because there may be depth copy problem?
For instance:
Class B;
Class A
{
....
private:
std::vector<B*> bvec;
public:
void setB(std::vector<B*>& value)
{
this->bvec = value;
}
};
void main()
{
....
std::vector<const B*> value; // and already has values
A a;
a.setB(value);
}
This example only assign the value to the class variable bvec inside A class. Do I need to use memcpy since I found that std::vector bvec; has pointer items? I am confused with the depth copy in C++, could you make me clear about that? Thank you.
Think about this, if you remove and delete an item from the vector value after you call setB, then the vector in A will have a pointer that is no longer valid.
So either you need to do a "deep copy", have guarantees that the above scenario will never happen, or use shared smart pointers like std::shared_ptr instead of raw pointers. If you need pointers, I would recommend the last.
There is another alternative, and that is to store the vector in A as a reference to the real vector. However, this has other problems, like the real vector needs to be valid through the lifetime of the object. But here too you can use smart pointers, and allocate the vector dynamically.
It is unlikely you need strcpy or memcpy to solve your problem. However, I'm not sure what your problem is.
I will try to explain copying as it relates to std::vector.
When you assign bvev to value in setB you are making a deep copy. This means all of the elements in the vector are copied from value to bvec. If you have a vector of objects, each object is copied. If you have a vector of pointers, each pointer is copied.
Another option is to simply copy the pointer to the vector if you wish to reference the elements later on. Just be careful to manage the lifetimes properly!
I hope that helps!
You probably want to define your copy constructor for class A to ensure the problem your asking about is handled correctly (though not by using memcpy or strcpy). Always follow the rule of three here. I'm pretty sure with std::vector your good, but if not, then use a for loop instead of memcpy
I need a collection in which i can store heap-allocated objects having virtual functions.
I known about boost::shared_ptr, std::unique_ptr (C++11) and boost::ptr_(vector|list|map), but they doesn't solve duplicate pointer problem.
Just to describe a problem - i have a function which accepts heap-allocated pointer and stores it for future use:
void SomeClass::add(T* ptr)
{
_list.push_back(ptr);
}
But if i call add twice with same parameter ptr - _list will contain two pointers to same object and when _list is destructed multiple deletion of same object will occur.
If _list will count pointer which he stores and uses them at deletion time then this problem will be solved and objects will not be deleted multiple times.
So the question is:
Does somebody knows some library with collections (vector,list,map in essence) of pointer with auto-delete on destruction and support of reference counting?
Or maybe i can solve this problem using some other technique?
Update:
I need support of duplicate pointers. So i can't use std::set.
As Kerrek SB and Grizzly mentioned - it is a bad idea to use raw pointers in general and suggests to use std::make_shared and forget about instantiation via new. But this is responsibility of client-side code - not the class which i designs. Even if i change add signature (and _list container of course) to
void SomeClass::add(std::shared_ptr<T> ptr)
{
_list.push_back(ptr);
}
then somebody (who doesn't know about std::make_shared) still can write this:
SomeClass instance;
T* ptr = new T();
instance.add(ptr);
instance.add(ptr);
So this is not a full solution which i wait, but useful if you write code alone.
Update 2:
As an alternative solution i found a clonning (using generated copy constructor). I mean that i can change my add function like this:
template <typename R>
void SomeClass::add(const R& ref)
{
_list.push_back(new R(ref));
}
this will allow virtual method (R - class which extends some base class (interface)) calls and disallow duplicate pointers. But this solution has an overhead for clone.
Yes: std::list<std::shared_ptr<T>>.
The shared pointer is avaiable from <memory>, or on older platforms from <tr1/memory>, or from Boost's <boost/shared_ptr.hpp>. You won't need to delete anything manually, as the shared pointer takes care of this itself. You will however need to keep all your heap pointers inside a shared pointer right from the start:
std::shared_ptr<T> p(new T); // legacy
auto p = std::make_shared<T>(); // better
If you another shared pointer to the same object, make a copy of the shared pointer (rather than construct a new shared pointer from the underlying raw pointer): auto q = p;
The moral here is: If you're using naked pointers, something is wrong.
Realize that smart pointers are compared by comparing the underlying container. So you can just use a std::set of whatever smartpointer you prefer. Personally I use std::unique_ptr over shared_ptr, whenever I can get away with it, since it makes the ownership much clearer (whoever holds the unique_ptris the owner) and has much lower overhead too. I have found that this is enough for almost all my code. The code would look something like the following:
std::set<std::unique_ptr<T> > _list;
void SomeClass::add(T* ptr)
{
std::unique_ptr<T> p(ptr);
auto iter = _list.find(p);
if(iter == _list.end())
_list.insert(std::move(p));
else
p.release();
}
I'm not sure right now if that is overkill (have to check if insert is guaranteed not to do anything, if the insertion fails), but it should work. Doing this with shared_ptr<T> would look similar, although be a bit more complex, due to the lack of a relase member. In that case I would probably first construct a shared_ptr<T> with a do nothing deleter too pass to the call to find and then another shared_ptr<T> which is actually inserted.
Of course personally I would avoid doing this and always pass around smart pointers when the ownership of a pointer changes hands. Therefore I would rewrite SomeClass::add as void SomeClass::add(std::unique_ptr<T> ptr) or void SomeClass::add(std::shared_ptr<T> ptr) which would pretty much solve the problem of having multiple instances anyways (as long as the pointer is always wrapped).
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Uses for multiple levels of pointer dereferences?
I saw a question about ** (pointer to a pointer) in C here. I'd like to know whats the point of this? When should I use it?
Whenever You need a pointer to a pointer :).
For example, if You want to dynamically allocate an array of pointers, operator new or malloc will return a pointer pointing to the first pointer in the array.
Other use might be, to pass a pointer to pointer, to a function, so the function can modify the original pointer. In C++, You can pass by reference, but not in C.
When you have a function which wants to increment a pointer to a c-string. This is needed for things like recursive-descent parsers where each rule is responsible for incrementing things...
In some variation of this:
void PutNewObjectHere(Class **dp) {
*dp = new Class;
}
Class *p;
PutNewObjectHere(&p);
delete p;
(Note, this is a silly example for illustration. It would normally return the new pointer. The concept, however, does occasionally come up in practice)
It's commonly used for out parameters that are pointers, e.g.:
bool GetSomeObject(SomeObject** object) {
*object = new SomeObject();
// ... initialize object or whatever ...
}
And you would call it like thus:
SomeObject* object;
if (GetSomeObject(&object)) {
// ... use object ...
delete object;
}
This is a common pattern where the callee allocates and the caller frees...
You want a C function to mutate a pointer passed as argument, and it's C so there's no pass-by-reference. Therefore you pass a pointer to the pointer. Here's a favorite example adapted from Dave Hanson's C Interfaces and Implementations:
void Bit_free(struct Bit_T **set) {
assert(set && *set);
free(*set);
*set = NULL;
}
By writing NULL into the freed pointer, you prevent it from dangling.
This is called double indirection, meaning you have a pointer to another pointer, which in turn points to some useful data (or in rare cases yet another pointer).
There's a good article at Wikipedia that covers pointers in general and has a good section on double indirection.
In particular I've used these kind of pointers in the context of an array. For instance in my 8086 emulator project I had an array of function pointers. So it ended up looking like this:
instruction_functions[(int)opcode]();
This is also known as a jump table(sorta) and is used in a lot of places for optimization purposes.