Reputation: 383
I am used to programming in C, and in that language I would just return a pointer to the data, and then the caller would be responsible for freeing the data, however, from what I've read, the vector's destructor will be called as soon as it goes out of scope, causing it's data to be de-allocated.
Once the reference is returned, the size of the contents will not change, so if I could just have a pointer to the data that I could manually delete afterwards that would be ideal. What I really do not want to do is copy all of the data into a new container, since this vector is going to grow to be very large.
Any help would be appreciated. Every solution I have seen so far involves either copying by value and relying on the compiler to optimize it, or using additional classes to wrap the vector.
Edit: To be clear, the only part of the vector which I want to keep is a pointer to its data (I.E. the pointer you get using the vector.data() method), I don't need to keep any other information about the original vector.
Upvotes: 1
Views: 1013
Reputation: 56
It is not possible to preserve the reference to a vector after it goes out of scope because, and you mentioned, it will be deleted. Once the vector is deleted, the memory stored at that address will be inaccessible. Alternatively, you can declare the variable outside of the scope, edit it within the scope. You mention returning by reference - is it possible that you can pass the vector into the function by reference, and simply return void? This way, you can edit the same vector in different scopes.
Upvotes: 0
Reputation: 238351
Good (safe and fast) solution for the use case that you describe: Don't return a reference, return the vector to the outside of the scope instead.
Is it possible to return an a reference to the data in an std::vector, and preserve that reference after the vector goes out of scope?
Yes... if you use static storage. The lifetime of objects with static storage duration extends until the end of the program. Therefore they stay alive when they go out of scope. Note that static storage is global state, which is often problematic. Avoid if you can and use with care.
With automatic storage: No.
I would just return a pointer to the data, and then the caller would be responsible for freeing the data
This is a problematic approach. How does the caller know that they are responsible for freeing the data? How does the caller know how to free the data? How does the caller know when they can free the data (in case there are other users of the data)? This all relies on the caller to read the documentation, understand it, and not make a mistake. This is a source of many memory leaks, accesses through invalid pointers and double free crashes.
std::vector
solves those problems (to some degree; there are no interfaces in C or C++ that cannot be misused if one tries hard enough) by keeping the lifetime tied to the container object.
If I could just have a pointer to the data that I could manually delete afterwards that would be ideal.
You cannot have that. std::vector
always destroys its data, and it is not possible to steal the data to the outside of the vector (except into another vector through move or swap).
Upvotes: 3
Reputation: 25388
Just write your code like this:
std::vector<blah> my_function_that_returns_a_vector ()
{
std::vector <blah> v;
... code to populate v ...
return v;
}
NVRO will then eliminate the copy. Instead, the vector returned is constructed directly in the caller's stack frame.
Upvotes: 2
Reputation: 41281
The whole point of a reference is that it doesn't own the object. It's perfectly valid to use a std::unique_ptr
here, which owns the object and can be returned to your caller.
Your function would be defined as follows (I assume a vector of integers), and C++14 or newer:
std::unique_ptr<std::vector<int>> getVector() {
auto vec = std::make_unique<std::vector<int>>(/*any ctor args you want*/);
// for example
vec->push_back(1);
vec->push_back(2);
return vec;
}
A caller can then do as follows:
int main() {
auto vec = getVector();
std::cout << vec->size() << std::endl;
}
and the vector will be safely deleted as the unique_ptr
goes out of scope. Note that if you are using C++11, you won't have std::make_unique
and will need to do something like:
std::unique_ptr<std::vector<int>> vec(new std::vector<int>(/* ctor args */));
Upvotes: 3