unique_ptr to char* conversion - c++

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!

Related

Best way to wrap a char* in C++?

In my code I use buffers currently allocated this way:
char* buf1 = (char*)malloc(size);
However at some points in the code I want to reassign the pointer to some place else in memory. The problem is that there are other places in the code that still need to be able to access the pointer buf1.
What's the best way to do this in C++? Right now I am considering writing a struct with a single char* in it, then allocating an object of this struct type and passing it to the places where I need to, and referring to wrapped pointer to get the current value of buf1.
However it seems that this is similar to what unique_ptr does. If I use unique_ptr how can I wrap a char* with it? I had some trouble with testing this and I'm not sure it's supported.
To clarify: these buffers are bytes of varying sizes.
In general, this question cannot be answered. There are simply way too many things you could be wanting to be doing with an array of char. Without knowing what it actually is that you want to do, its impossible to say what may be good abstractions to use…
If you want to do stuff with strings, just use std::string. If you want a dynamically-sized buffer that can grow and shrink, use std::vector.
If you just need a byte buffer the size of which is determined at runtime or which you'd just generally want to live in dynamic storage, I'd go with std::unique_ptr. While std::unique_ptr<T> is just for single objects, the partial specialization std::unique_ptr<T[]> can be used for dealing with dynamically allocated arrays. For example:
auto buffer = std::unique_ptr<char[]> { new char[size] };
Typically, the recommended way to create an object via new and get an std::unique_ptr to it would be to use std::make_unique. And if you want your buffer initialized to some particular value, you should indeed use std::make_unique<char[]>(value). However, std::make_unique<T[]>() will value-initialize the elements of the array it creates. In the case of a char array, that effectively means that your array will be zero-initialized. In my experience, compilers are, unfortunately, unable to optimize away the zero-initialization, even if the entire buffer would be overwritten first thing right after being created. So if you want an uninitialized buffer for the sake of avoiding the overhead of initialization, you can't use std::make_unique. Ideally, you'd just define your own function to create a default-initialized array via new and get an std::unique_ptr to it, for example:
template <typename T>
inline std::enable_if_t<std::is_array_v<T> && (std::extent_v<T> == 0), std::unique_ptr<T>> make_unique_default(std::size_t size)
{
return std::unique_ptr<T> { new std::remove_extent_t<T>[size] };
}
and then
auto buffer = make_unique_default<char[]>(new char[size]);
It seems that C++20 will include this functionality in the form of std::make_unique_default_init. So that would be the preferred method then.
Note that, if you're dealing with plain std::unique_ptr, you will still have to pass around the size of the buffer separately. You may want to bundle up an std::unique_ptr and an std::size_t if you're planning to pass around the buffer
template <typename T>
struct buffer_t
{
std::unique_ptr<T[]> data;
std::size_t size;
};
Note that something like above struct represents ownership of the buffer. So you'd want to use this, e.g., when returning a new buffer from a factory function, e.g.,
buffer_t makeMeABuffer();
or handing off ownership of the buffer to someone else, e.g.,
DataSink(buffer_t&& buffer)
You would not want to use it just to point some function to the buffer data and size do some processing without transferring ownership. For that, you'd just pass a pointer and size, or, e.g., use a span (starting, again, with C++20; also available as part of GSL)…

C++ Buffer pains

I need a class (in C++11) which stores a couple of fields(including a buffer). I started with malloc() in a constructor and free() in a destructor (I didn't touch C/C++ for quite some time so that was all I remembered).
Next thing I remembered (because of crashes) that I need to implement a copy constructor and an assignment operator. Now, I have a full screen of code just for a class with 3 fields (one of which is the buffer).
A question.
What should I use? (I am dazzled by amount of choices - std::vector, std::array, std::shared_ptr, boost::scoped_ptr and may be something else).
Functionality for this buffer which I am looking for are:
as little as possible memory management
getting rid of these copy constructors and assignment operators
ability to use it as void* (I have to pass it to functions which accept "void*")
ability to access read/write it randomly (I may need to get a random range out of it and write a random range to it)
allocate it on the heap (buffer can be reasonably large)
preferably usage of some standard facility
You should just use std::vector<unsigned char> as your buffer. This already has all the necessary constructors, operators, and destructor, so there's nothing special you need to do except use it.
I'm not a C++ expert, so I'd welcome any criticisms to this solution, but a smart pointer to an array might work.
#include <iostream>
#include <memory>
void do_something(void *buffer)
{
char* char_buffer = (char*)buffer;
std::cout << char_buffer[0] << std::endl;
}
int main()
{
size_t size = 10;
// reference counted pointer to auto-delete the buffer
std::shared_ptr<char> buffer(new char[size], std::default_delete<char[]>());
// use the underlying pointer
// http://stackoverflow.com/questions/27819809/why-is-there-no-operator-for-stdshared-ptr
buffer.get()[0] = 'a';
do_something(buffer.get());
// buffer deallocated at the end of scope
}
as little as possible memory management
The smart pointer takes care of that for you
getting rid of these copy constructors and assignment operators
I think the smart pointer handles them
ability to use it as void* (I have to pass it to functions which accept "void*")
Use .get() and a cast.
ability to access read/write it randomly (I may need to get a random range out of it and write a random range to it)
It's still a pointer at the end of this, so I can't see why that wouldn't work (I haven't tried it).
allocate it on the heap (buffer can be reasonably large)
It's on the heap
preferably usage of some standard facility
<memory>
Alternatively, checkout <vector>'s .data() function, which returns a pointer to the vector's underlying array.
I think you need some kind of memory buffer. Check this simple c++ buffer class.
Not using c++11 is intentional because of my company development environment.
https://github.com/jeremyko/CumBuffer

Best practice for std::auto_ptr

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.

Prototype for function that allocates memory on the heap (C/C++)

I'm fairly new to C++ so this is probably somewhat of a beginner question. It regards the "proper" style for doing something I suspect to be rather common.
I'm writing a function that, in performing its duties, allocates memory on the heap for use by the caller. I'm curious about what a good prototype for this function should look like. Right now I've got:
int f(char** buffer);
To use it, I would write:
char* data;
int data_length = f(&data);
// ...
delete[] data;
However, the fact that I'm passing a pointer to a pointer tips me off that I'm probably doing this the wrong way.
Anyone care to enlighten me?
In C, that would have been more or less legal.
In C++, functions typically shouldn't do that. You should try to use RAII to guarantee memory doesn't get leaked.
And now you might say "how would it leak memory, I call delete[] just there!", but what if an exception is thrown at the // ... lines?
Depending on what exactly the functions are meant to do, you have several options to consider. One obvious one is to replace the array with a vector:
std::vector<char> f();
std::vector<char> data = f();
int data_length = data.size();
// ...
//delete[] data;
and now we no longer need to explicitly delete, because the vector is allocated on the stack, and its destructor is called when it goes out of scope.
I should mention, in response to comments, that the above implies a copy of the vector, which could potentially be expensive. Most compilers will, if the f function is not too complex, optimize that copy away so this will be fine. (and if the function isn't called too often, the overhead won't matter anyway). But if that doesn't happen, you could instead pass an empty array to the f function by reference, and have f store its data in that instead of returning a new vector.
If the performance of returning a copy is unacceptable, another alternative would be to decouple the choice of container entirely, and use iterators instead:
// definition of f
template <typename iter>
void f(iter out);
// use of f
std::vector<char> vec;
f(std::back_inserter(vec));
Now the usual iterator operations can be used (*out to reference or write to the current element, and ++out to move the iterator forward to the next element) -- and more importantly, all the standard algorithms will now work. You could use std::copy to copy the data to the iterator, for example. This is the approach usually chosen by the standard library (ie. it is a good idea;)) when a function has to return a sequence of data.
Another option would be to make your own object taking responsibility for the allocation/deallocation:
struct f { // simplified for the sake of example. In the real world, it should be given a proper copy constructor + assignment operator, or they should be made inaccessible to avoid copying the object
f(){
// do whatever the f function was originally meant to do here
size = ???
data = new char[size];
}
~f() { delete[] data; }
int size;
char* data;
};
f data;
int data_length = data.size;
// ...
//delete[] data;
And again we no longer need to explicitly delete because the allocation is managed by an object on the stack. The latter is obviously more work, and there's more room for errors, so if the standard vector class (or other standard library components) do the job, prefer them. This example is only if you need something customized to your situation.
The general rule of thumb in C++ is that "if you're writing a delete or delete[] outside a RAII object, you're doing it wrong. If you're writing a new or `new[] outside a RAII object, you're doing it wrong, unless the result is immediately passed to a smart pointer"
In 'proper' C++ you would return an object that contains the memory allocation somewhere inside of it. Something like a std::vector.
Your function should not return a naked pointer to some memory. The pointer, after all, can be copied. Then you have the ownership problem: Who actually owns the memory and should delete it? You also have the problem that a naked pointer might point to a single object on the stack, on the heap, or to a static object. It could also point to an array at these places. Given that all you return is a pointer, how are users supposed to know?
What you should do instead is to return an object that manages its resource in an appropriate way. (Look up RAII.) Give the fact that the resource in this case is an array of char, either a std::string or a std::vector seem to be best:
int f(std::vector<char>& buffer);
std::vector<char> buffer;
int result = f(buffer);
Why not do the same way as malloc() - void* malloc( size_t numberOfBytes )? This way the number of bytes is the input parameter and the allocated block address is the return value.
UPD:
In comments you say that f() basically performs some action besides allocating memory. In this case using std::vector is a much better way.
void f( std::vector<char>& buffer )
{
buffer.clear();
// generate data and add it to the vector
}
the caller will just pass an allocated vector:
std::vector buffer;
f( buffer );
//f.size() now will return the number of elements to work with
Pass the pointer by reference...
int f(char* &buffer)
However you may wish to consider using reference counted pointers such as boost::shared_array to manage the memory if you are just starting this out.
e.g.
int f(boost::shared_array<char> &buffer)
Use RAII (Resource Acquisition Is Initialization) design pattern.
http://en.wikipedia.org/wiki/RAII
Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)
Just return the pointer:
char * f() {
return new char[100];
}
Having said that, you probably do not need to mess with explicit allocation like this - instead of arrays of char, use std::string or std::vector<char> instead.
If all f() does with the buffer is to return it (and its length), let it just return the length, and have the caller new it. If f() also does something with the buffer, then do as polyglot suggeted.
Of course, there may be a better design for the problem you want to solve, but for us to suggest anything would require that you provide more context.
The proper style is probably not to use a char* but a std::vector or a std::string depending on what you are using char* for.
About the problem of passing a parameter to be modified, instead of passing a pointer, pass a reference. In your case:
int f(char*&);
and if you follow the first advice:
int f(std::string&);
or
int f(std::vector<char>&);
Actually, the smart thing to do would be to put that pointer in a class. That way you have better control over its destruction, and the interface is much less confusing to the user.
class Cookie {
public:
Cookie () : pointer (new char[100]) {};
~Cookie () {
delete[] pointer;
}
private:
char * pointer;
// Prevent copying. Otherwise we have to make these "smart" to prevent
// destruction issues.
Cookie(const Cookie&);
Cookie& operator=(const Cookie&);
};
Provided that f does a new[] to match, it will work, but it's not very idiomatic.
Assuming that f fills in the data and is not just a malloc()-alike you would be better wrapping the allocation up as a std::vector<char>
void f(std::vector<char> &buffer)
{
// compute length
int len = ...
std::vector<char> data(len);
// fill in data
...
buffer.swap(data);
}
EDIT -- remove the spurious * from the signature
I guess you are trying to allocate a one dimensional array. If so, you don't need to pass a pointer to pointer.
int f(char* &buffer)
should be sufficient. And the usage scenario would be:
char* data;
int data_length = f(data);
// ...
delete[] data;

How should I change this declaration?

I have been given a header with the following declaration:
//The index of 1 is used to make sure this is an array.
MyObject objs[1];
However, I need to make this array dynamically sized one the program is started. I would think I should just declare it as MyObject *objs;, but I figure if the original programmer declared it this way, there is some reason for it.
Is there anyway I can dynamically resize this? Or should I just change it to a pointer and then malloc() it?
Could I use some the new keyword somehow to do this?
Use an STL vector:
#include <vector>
std::vector<MyObject> objs(size);
A vector is a dynamic array and is a part of the Standard Template Library. It resizes automatically as you push back objects into the array and can be accessed like a normal C array with the [] operator. Also, &objs[0] is guaranteed to point to a contiguous sequence in memory -- unlike a list -- if the container is not empty.
You're correct. If you want to dynamically instantiate its size you need to use a pointer.
(Since you're using C++ why not use the new operator instead of malloc?)
MyObject* objs = new MyObject[size];
Or should I just change it to a
pointer and then malloc() it?
If you do that, how are constructors going to be called for the objects in on the malloc'd memory? I'll give you a hint - they won't be - you need to use a std::vector.
I have only seen an array used as a pointer inside a struct or union. This was ages ago and was used to treat the len and first char of a string as a hash to improve the speed of string comparisons for a scripting language.
The code was similar to this:
union small_string {
struct {
char len;
char buff[1];
};
short hash;
};
Then small_string was initialised using malloc, note the c cast is effectively a reinterpret_cast
small_string str = (small_string) malloc(len + 1);
strcpy(str.buff, val);
And to test for equality
int fast_str_equal(small_string str1, small_string str2)
{
if (str1.hash == str2.hash)
return strcmp(str1.buff, str2.buff) == 0;
return 0;
}
As you can see this is not a very portable or safe style of c++. But offered a great speed improvement for associative arrays indexed by short strings, which are the basis of most scripting languages.
I would probably avoid this style of c++ today.
Is this at the end of a struct somewhere?
One trick I've seen is to declare a struct
struct foo {
/* optional stuff here */
int arr[1];
}
and malloc more memory than sizeof (struct foo) so that arr becomes a variable-sized array.
This was fairly commonly used in C programs back when I was hacking C, since variable-sized arrays were not available, and doing an additional allocation was considered too error-prone.
The right thing to do, in almost all cases, is to change the array to an STL vector.
Using the STL is best if you want a dynamically sizing array, there are several options, one is std::vector. If you aren't bothered about inserting, you can also use std::list.
Its seems - yes, you can do this change.
But check your code on sizeof( objs );
MyObj *arr1 = new MyObj[1];
MyObj arr2[1];
sizeof(arr1) != sizeof(arr2)
Maybe this fact used somewhere in your code.
That comment is incredibly bad. A one-element array is an array even though the comment suggests otherwise.
I've never seen anybody try to enforce "is an array" this way. The array syntax is largely syntactic sugar (a[2] gives the same result as 2[a]: i.e., the third element in a (NOTE this is an interesting and valid syntax but usually a very bad form to use because you're going to confuse programmers for no reason)).
Because the array syntax is largely syntactic sugar, switching to a pointer makes sense as well. But if you're going to do that, then going with new[] makes more sense (because you get your constructors called for free), and going with std::vector makes even more sense (because you don't have to remember to call delete[] every place the array goes out of scope due to return, break, the end of statement, throwing an exception, etc.).