0

So I have a project that makes the user input an option op on which depends the type of the vector it will be used, that is vector<int> vector<float> and vector<double>.

To do this, I have created 3 functions that will be called depending on op, and it works like this:

    #include <iostream>
    #include <vector>

    using namespace std;
    typedef vector<int> intv;
    typedef vector<float> flov;
    typedef vector<double> douv;
    intv vectori(int opt, int t);
    flov vectorf(int opt, int t);
    douv vectord(int opt, int t);

    int main(){
    int opt;
    size_t t;
    cout << "Size: \n";
    cin >> t;
    cout << "Option? \n";
    cin >> op;
    flov vf;
    douv vd;
    intv vi;
    switch (op){
            case 00:
                    vi.reserve(t);
                    vi=vectori(0,t);
                    break;
            case 01:
                    vf.reserve(t);
                    vf=vectorf(0,t);
                    break;
            case 02:
                    vd.reserve(t);
                    vd=vectord(0,t);
                    break;

                  }
    }

This would be the example vectori function:

intv vectori(int op, int t)
{
intv v;
v.reserve(t);
// Do stuff
return v;
}

And the example vectorf function is analogous (So is vectord):

flov vectorf(int op, int t)
{
flov v;
v.reserve(t);
// Do stuff
return v;
}

So the questions are:

  • What is the memory cost of the statement vector vf , Considering I am not reserving memory for it if it is not needed.
  • What happens with the variable v once the function vectorx ends? Does returning v and calling it vi create a copy of v in memory?
  • Is this overall memory efficient?
SirDarius
  • 41,440
  • 8
  • 86
  • 100
D1X
  • 5,025
  • 5
  • 21
  • 36
  • 2
    `reserve` You are using it way too much and some are redundant, which aren't going to be helpful. Better is you profile it and see for yourself. No way can the efficiency be predicted without running it. Those who predict by looking at the code, are only fooling themselves. – DumbCoder Feb 09 '15 at 09:30
  • Any reason why you want to use octal in the `case`? – James Kanze Feb 09 '15 at 10:48
  • Not really, I have copied a fraction of the code, using octal was for presentation purposes. (When using cout). – D1X Feb 10 '15 at 12:26

4 Answers4

1

What is the memory cost of the statement vector vf, Considering I am not reserving memory for it if it is not needed.

(I assume you mean the flov vf; statement). As a general guideline, the memory usage will be roughly sizeof(the_vector) + sizeof(element_type) * the_vector.capacity(). There may be more for implementation-specific debugging information, rounding up to memory-allocation page size if your implementation's too stupid to do that while increasing capacity....

Note that std::vector guarantees contiguous memory so the potential for large quantities of unexpected implementation-specific wasted memory is massively less than say std::map, where the memory's fragmented and each individual node may be hit with overheads for allocation, debug information etc..

What happens with the variable v once the function vectorx ends? Does returning v and calling it vi create a copy of v in memory?

With C++11 you can expect that either vi will be directly populated with the data vectorf() nominally returns (due to Return Value Optimisation), or it will be move-constructed, which means effectively that vi will take ownership of the pointer-to-dynamically-allocated-memory where the vector elements are stored. It's relatively lightweight, and doesn't get slower as the number of elements being handled increases.

For that reason, you should not reserve memory in vi, vf, nor vd before assigning to them the returned vectors... you may end up allocating and releasing the additional capacity without having it used at all.

Is this overall memory efficient?

For large values of t, the overheads of having unnecessary variables become insignificant, so yes. Do take into account the reserve issue mentioned above though - as is your momentary memory usage during assignment may be unnecessarily excessive.


All that said, if you're ultimately choosing one of the three types of data for the program to use during that run, you may be better off using a template and structure like this:

#include <iostream>
#include <vector>

template <typename T>
void f(int t)
{
    std::vector<T> v(t);
    ... do all your work with v...
}

int main()
{
    int opt;
    size_t t;
    if (std::cout << "Size:\n" && 
        std::cin >> t &&
        std::cout << "Option? \n" &&
        std::cin >> op)
    {
        switch (op)
        {
          case 00: f<int>(t); break;
          case 01: f<float>(t); break;
          case 02: f<double>(t); break;
        }
    }
    else
        std::cerr << "unable to read inputs from stdin\n";
}
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Okay, so the first modification I should do is to remove the reserve statements for vi, vf, vd. – D1X Feb 09 '15 at 10:15
  • @D1X: that's right - all the `reverse` statements in the `main()` function are counter-productive.... – Tony Delroy Feb 09 '15 at 10:17
1

What is the memory cost of the statement vector vf , Considering I am not reserving memory for it if it is not needed.

The standard doesn't specify what the initial capacity of a container should be, so you're relying on the implementation (see Initial capacity of vector in C++)

Anyway many implementations will start the capacity at zero.

What happens with the variable v once the function vectorx ends? Does returning v and calling it vi create a copy of v in memory?

This depends on compiler. Most recent compilers will apply Return Value Optimization or use the move constructor (see How to "return an object" in C++? and C++ vector, return vs. parameter).

Is this overall memory efficient?

I think it can be improved.

  1. you're using reserve too much
  2. you could simplify your code with a variant type (e.g see boost variant).
Community
  • 1
  • 1
manlio
  • 18,345
  • 14
  • 76
  • 126
0
  • for the memory cost, you'll need to profile it as DumbCoder suggeted, it is system specific.

  • variable v is local to the procedure, so it will be freed at the end of it. The return normally would create a copy, unless your compiler has some optimisation. Research on "Return Value Optimisation", this is compiler specific.

  • another better way to do vector passing is via parameter by reference void funct(std::vector &vec, ...)

Vincent Ho
  • 106
  • 7
0

What is the memory cost of the statement vector vf;, considering I am not reserving memory for it if it is not needed.

Technically, this depends on the standard library implementation. It would be within its rights to pre-allocate some memory (that is, start with non-zero capacity()). But I don't think any implementation actually does it—it would be very wasteful if the vector is then assigned to (like what you're doing).

If you want to be 100% sure, inspect your standard library's implementation of vector::vector(), but I really expect there is no dynamic memory allocation involved.

What happens with the variable v once the function vectorx ends? Does returning v and calling it vi create a copy of v in memory?

In C++11 and beyond, the answer is no, no extra copy is made. The vector v is moved into the vector vi (the buffer ownership is transferred).

In C++03, a copy would likely have occurred. If the compiler was smart enough, it might figure out that it can construct the returned vector directly in vi, but I fear it might be too big a mental leap. To be sure, inspect assembly.

Is this overall memory efficient?

Yes, there's unlikely to be any unused heap memory involved. And the vector object itself likely takes up only 3 pointer sizes on the stack.

Except this: DumbCoder pointed out a serious flaw in your code—the calls to reserve() on vi and similar vectors. These do nothing to help. Either the vector takes ownership of v's buffer (in C++11, moved), or it will know how much memory to allocate anyway (v.size()), so there will be no unnecessary reallocations. reserve() only makes sense if you expect ot add to the vector multiple times (e.g. a loop of push_back() calls), and don't want unnecessary reallocations to happen during that.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455