0

The question should be fairly simple, but I'm not a C++ programmer.

So imagine I have a std::vector filled with something as a local variable in a function. What I want to do is to return pointer to that data and count from that function, but not the vector itself (because it goes to another language, not C++). So what is the best way to do it?

I bet I can declare vector with new keyword, but when I later call free() on its pointer data, will there be a leak?

I can also malloc() new buffer, copy vector's buffer into that and return fresh one, but I wish I can avoid that.

s1ddok
  • 4,615
  • 1
  • 18
  • 31
  • How do you send the data to the other language? Can you just return the vector itself and then send the internal pointer of the returned vector using `v.data()`? – Galik May 10 '17 at 12:29
  • 2
    The `vector` must live somewhere while the other language is using it. You either need to not return from the function until the other language is done or move the `vector` into some persistent space or give the responsibility of keeping the `vector` alive to the other language. Any of these solutions would work, but your question doesn't contain enough information to know which one is appropriate. – nwp May 10 '17 at 12:43
  • 1
    `malloc` with `free`, and `new` with `delete`. Don't cross those streams. And don't try to delete the `vector`'s data from under its nose; that's not nice. –  May 10 '17 at 12:47
  • Declarate vector outside the the function. Pass pointer or link on the vector into function. Fill the vector inside function. You don't need to call "new"/"delete" - the vector is doing it instead you ;) – Dmytro Khmara May 10 '17 at 13:47

3 Answers3

2

You can declare your function with the std::vector<T>& as an argument and return only the vector.count() (See Pass by reference in C++). Latter, in client code pass an empty constructed vector to that function.

To get pointer to raw data, you can use &vector[0] or &vector.front(). Starting from C++11, there are a newly added member function in vector: data(), which returns the address of the initial element in the container.

In general, don't use unnecessary malloc/free operations and avoid the use of heap allocation when it is not necessary. Consider smart pointers instead of raw pointers and make_shared/make_unique instead of explicit new.

Narek Atayan
  • 1,479
  • 13
  • 27
0

If your vector contains basic types (for example int) and you know the memory will be deallocated with free you can just use:

if(v.empty()) return NULL;
int* retResut;
retResut= reinterpret_cast<int*>(std::malloc(v.size() * sizeof(int)));
std::memcpy(retResut,v.data(),v.size()* sizeof(int));
return retResut 
IlBeldus
  • 1,040
  • 6
  • 14
  • The question explicitly states "without memory leaks". – nwp May 10 '17 at 12:53
  • @nwp from original question: "but when I later call free()" so I assumed calling free later is an option. – IlBeldus May 10 '17 at 12:57
  • That's the option I considered in the question intself, but thanks! As far as I can see my question has only one answer: "impossible" – s1ddok May 10 '17 at 13:49
0

Asuming you need to declare a function that has the following definition: SomeType* foo();. You can used std::vector::data to get a raw pointer to the data (c++11). In case of c++03 you can use &my_vector[0] (and you must check for empty vector in order to avoid runtime debug aserts)

There is one thing to take into consideration; is it called from multiple threads or not:

  1. when you have only one thread calling foo:

    std::vector<SomeType>& get_buffer()
    {
        static std::vector<SomeType> data;
        return data;
    }
    SomeType* foo()
    {
        std::vector<SomeType>& buffer = get_buffer();
        buffer.clear();
    
        //fill buffer with stuff with push_back
    
        return buffer.data();
    }
    
  2. When called from multiple threads. The static variable is initialized properly however the push_back function is not thread safe. You also need a different buffer for each thread but this does not guarantee total safely (considering you have no way of knowing how long the lifetime of that data should be). get_buffer should return a unique std::vector for the each thread. You can use thread local storage by changing static into thread_local (see this):

    std::vector<SomeType>& get_buffer()
    {
        thread_local std::vector<SomeType> data;
        return data;
    }
    

    Node that thread_local is since c++11 if you are using c++03 you need to use boost library or platform specific code.

Community
  • 1
  • 1
Raxvan
  • 6,257
  • 2
  • 25
  • 46