Background
If I had a function foo as follows
void foo(std::vector<int>& values)
{
values = std::vector<int>(10, 1);
}
Then I could call it as
std::vector<int> values;
foo(values);
Notice that the initial vector is empty, then it is populated within the function foo.
I often come across interfaces that I cannot change (i.e. 3rd party), that have the same intention as above, but using raw arrays, for example
void foo(int*& values)
{
values = new int[10];
std::fill_n(values, 10, 1);
}
My problem with these is that now I am responsible for managing that memory, e.g.
int* values;
foo(values);
delete[] values;
Question
Is there any way I can use smart pointers to manage this memory for me? I would like to do something like
std::unique_ptr<int[]> values;
foo(values.get());
but get returns a pointer that is an r-value, so I cannot pass it by non-const reference.
Create empty unique_ptr.
Create pointer.
Pass pointer to function.
Reset unique_ptr to that pointer.
Like that:
std::unique_ptr<int[]> values;
int* values_ptr;
foo(values_ptr);
values.reset(values_ptr);
Or:
int* values_ptr;
foo(values_ptr);
std::unique_ptr<int[]> values(values_ptr);
Simple answer: you cannot.
But i believe there is a way to simplify you life. Since you always do the same thing, you simply have to write a function that does it for you and call that function when you need. Since i suppose you want to use the returned value written in memory before releasing it, i make my function return it.
template <typename T, typename Function>
std::unique_ptr<T[]> call(Function f) {
T * value;
f(value);
return { value };
}
// then to use it
auto value = call<int>(foo);
Would that suit you?
The function could be improved to detect the difference for pointers to one object or to an array if you need it, and it could probably also be improved to detect automatically the needed parameter type so that you do not have to type it.
Related
So as the title says, I'm wondering what the proper way to move an element in an array such as:
std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, N> data;
Is it as simple as doing:
data[dst] = data[src];
Or do I need to add something else like a move, being that its storage is uninitialized, do I need to use the copy or move constructors, something like:
new (&data[dst]) T(std::move(data[src]));
Since the data[src] is not the proper type T, do i need to instead do:
new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));
I'm looking for the most flexible way of moving the item for anything T might be, including move only types etc.
Basically I'm creating a packed array that always moves elements to be contiguous in memory, even when ones are removed to prevent holes in the active section of the array.
Edit:
As the comments want a minimal example, I guess something like:
template<class T, std::size_t N>
class SimpleExampleClass {
std::array<std::aligned_storage_t<sizeof(T), alignof(T)>, N> data;
public:
void move_element(std::size_t src, std::size_t dst) {
// data[dst] = data[src]; ?
// or
// new (&data[dst]) T(std::move(data[src]));
// or
// new (&data[dst]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[src])));
// or
// something else?
// then I would need some way to clean up the src element, not sure what would suffice for that.
// as calling a destructor on it could break something that was moved potentially?
}
// Other functions to manipulate the data here... (example below)
template<typename ...Args>
void emplace_push(Args&&... args) noexcept {
new (&data[/*some index*/]) T(std::forward<Args>(args)...);
}
void push(T item) noexcept {
emplace_push(std::move(item));
}
};
std::aligned_storage itself is, roughly speaking, just a collection of bytes. There is nothing to move, and std::move(data[src]) is just a no-op. You should first use placement new to create an object and then you can move that object by move-constructing it at the new location.
Simple example:
auto ptr = new (&data[0]) T();
new (&data[1]) T(std::move(*ptr));
std::destroy_at(ptr);
in the case of T being something like unique_ptr, or any other similar edge case, there shouldn't be any issue with calling the destroy on the old element index correct?
Moving from an object leaves it in some valid state, and the object still has to be destroyed.
since data[0] is just a collection of bytes, would a pointer to it work, or would that pointer need to be reinterpret cast before being used in the move constructor?
It will work if it is adorned with reinterpret_cast and std::launder, like you wrote in your question:
new (&data[1]) T(std::move(*std::launder(reinterpret_cast<T*>(&data[0]))));
The Standard library contains some useful functions for working with uninitialized memory. The complete list can be found here (see the Uninitialized storage section).
I am trying to give the nullpointer wrapped as a unique pointer as the default argument to a function. Using only pointers the header might look like this
double f(A* vec = nullptr);
Since I do however need to use a unique_ptr, I tried to change it to
double f(std::unique_ptr<A>& A vec = nullptr);
or
double f(std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
Which results in the errors
could not convert ‘nullptr’ from ‘std::nullptr_t’ to ‘std::unique_ptr&’
and
cannot bind non-const lvalue reference of type ‘std::unique_ptr&’ to an rvalue of type ‘std::unique_ptr’
respecively. Is there a way to do this? I am relatively new to C++, so the answer might be obvious.
Not relevant to the question, but an explanation for my choice of unique_ptr: The parameter vec is used as the start value for an iteration in f and an improved value is returned with the pointer. The plan was that if no start value is given the pointer is set to the nullptr and a start value is calculated during the program. Since I however generate a new object, it would from all I can see be safer to use unique_ptr over a naked pointer.
I would say you have two optione here.
1) The function does not own the pointer it merely uses it. In this case pass a raw pointer or (better) a reference (if nullptr is not an option).
// correct way to express a call to a non-owning function.
double f(A* vec = nullptr);
Calling code will use the function like this:
std::unique_ptr<A> vec;
f(vec.get()); // pass the raw pointer to the function
2) The function needs to manage the life of the pointer or reseat the pointer (own it) in which case accept a std::unique_ptr by value.
// way to express transfer of ownership to a function
double f(std::unique_ptr<A> vec = std::unique_ptr<A>());
There is really no need to accept a reference if the function needs to take ownership of the pointer.
In discussions a third option has presented itself.
3) The function is expected to modify the pointer if you pass one in otherwise it will use its own internal pointer.
This is unusual but you could do this with a pair of overloaded functions like this:
// way to express a function that modifies a smart pointer
// (for example reseating it)
double f(std::unique_ptr<A>& vec);
// version where the uses doesn't want to supply the pointer
// and doesn't care about the modified value.
double f()
{
std::unique_ptr<A> vec; // a dummy
f(vec); // pass in the dummy
}
The second error is because you are binding a non-const reference to a rvalue (which it kind of says). If that is a must, you cannot use a default value, or use a const reference:
double f(const std::unique_ptr<A>& A vec = std::unique_ptr<A>(nullptr));
double f(std::unique_ptr<A>& vec = nullptr);
doesn't work since the compiler has to create a temporary std::unique_ptr from nullptr. Had you used
double f(std::unique_ptr<A> const& vec = nullptr);
the compiler would have accepted it.
One work around is to overload.
double f(std::unique_ptr<A>& vec)
{
return 0;
}
double f()
{
std::unique_ptr<A> vec = nullptr;
return f(vec);
}
I want to change the output tensor's underlying storage during an op.
I have a raw pointer(float*) of the new data. I want to set the output tensor to this new data before launch kernel and return, so that I can hijack this op.
However I am confusing with when should I delete the raw pointer, since the the tensor construct seems to be a shallow copy. I can only delete the raw pointer after all this tensor's usage finished. But how can I be notified this?
There is no public API for doing this inside the TensorFlow runtime, but it is possible to create a Tensor object from a raw pointer using the C API method TF_NewTensor(), which has the following signature:
// Return a new tensor that holds the bytes data[0,len-1].
//
// The data will be deallocated by a subsequent call to TF_DeleteTensor via:
// (*deallocator)(data, len, deallocator_arg)
// Clients must provide a custom deallocator function so they can pass in
// memory managed by something like numpy.
extern TF_Tensor* TF_NewTensor(TF_DataType, const int64_t* dims, int num_dims,
void* data, size_t len,
void (*deallocator)(void* data, size_t len,
void* arg),
void* deallocator_arg);
Internally, this creates a reference-counted TensorBuffer object that takes ownership of the raw pointer. (Unfortunately, only the C API has friend access to create a tensorflow::Tensor from a TensorBuffer directly. This is an open issue.) The deallocator function is called with the values of data, len and dellocator_arg when the reference count drops to zero.
Unfortunately, this is too little information to give you a precise answer. Possibly, you're not even allowed to delete the pointer!
Imagine something like this:
float* gf = nullptr; // global pointer (just for illustration)
void calculate()
{
float f;
gf = &f;
doSomething();
gf = nullptr;
}
Same applies, if your pointer in question points to some class-static or global variable.
If you create your variable on the heap, then delete it when you know you don't need it any more, which can be handled quite locally (typically), such as in this example:
class C
{
std::vector<float>values;
C(size_t num) : values(num, 0.0f) { }
~C() { } // data deleted automatically with vector
void function()
{
for(float& f : values)
{
gf = &f;
doSomething();
}
gf = nullptr;
}
};
Missing the explicit call to operator delete[]? Well, the vector handles this implicitly for me, so I don't have to bother. Even if you are forced to use raw pointers, you can avoid explict deletion by use of e. g. std::unique_ptr... Attention with the vector, though: the pointer might get invalid, if you add new elements to the vector or remove contained ones from it!
In my examples, I set the gf pointer explicitly to nullptr so that you can inspect when there is no float value in use - you'd have to check for while hijacking, of course... Be aware that in an multithreaded environment, you possibly might protect your pointer against race conditions.
Let's say my function:
vector<MyClass>* My_func(int a)
{
vector<MyClass>* ptr = new vector<MyClass>;
//...... Add a lot of elements to this vector, and let's say MyClass is also relatively big structure.
return ptr;
}
This method leaves responsibility for user to free the pointer.
Another method I can think of is just creating local variable in function and return the value:
vector<MyClass> My_func(int a)
{
vector<MyClass> vec;
//...... Add a lot of elements to this vector, and let's say MyClass is also relatively big structure.
return vec;
}
This one avoid the responsibility for user but may take a lot of space when return and copy the value.
Maybe smart pointer in C++ is a better choice but I am not sure. I did not use smart pointer before. What do people do when they come across this situation? What kind of return type will they choose?
Thanks ahead for your tips:-)
In most cases of this sort of construct, the compiler will do "Return Value Optimisation", which means that it's not actually copying the data structure being returned, but instead writing straight into one that lives on the place where it will be returned to.
So, you can safely do this without worrying about it being copied.
However, another method would be to not return a vector in the first, place, but request that the calling code pass one in:
So, something like:
void My_func(int a, vector<MyClass>& vec)
{
...
}
This is GUARANTEED to avoid copying.
In many situations return value optimizations easily can take care of the unnecessary copying. The question is: how are you planning to use this vector outside the function? If you have something like:
vector<MyClass> ret = My_func(a);
Then the optimizations can take care of the problem.
On the other hand, if you want to reuse an existing vector, you could pass a non-const reference to an existing vector, but there aren't many situations where this is needed or useful.
vector<MyClass> ret;
// do something with ret ...
My_func(a, ret);
Plus, this also changes the semantics of your function (e.g. you may need to clear() the vector).
Here is the internal structure of a vector
template <typename T>
class vector {
private:
size_t m_size;
size_t m_cap;
T * m_data;
public:
//methods push pop etc.
};
As you can the size of the vector (with 2 additional size_t data members) is not much larger than size of a pointer. There will be negligible performance benefit in passing a vector instead of pointer, infact using a pointer, accessing the vector will be slower as each time you will have to dereference the pointer. Generally, we don't create a pointer to a vector.
Also, never return a pointer to a local variable. The memory of the local variable will be wiped off once you return value & go out of the scope of the method. Ideally, you should create a vector in the calling function and pass a reference to the vector, when calling your method My_func.
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;