2

Possible Duplicate:
initializer_list and move semantics

Environment: Linux, g++-4.7

I used std::vector and a class of my own to test this. And I found that when using the std::initializer_list to construct a vector, it actually calls the copy constructor of the custom class to make a temporary object. Therefore, I consider it really unefficient and I used "const std::initializer_list & li" to replace it.

Why is it really common in STL library?? Eg:

// This is in STL: stl_vector.h
vector(initializer_list<value_type> __l, const allocator_type & __a = allocator_type())
//...

Is there actually something skiped my mind?

My test code is shown below:

#include <iostream>
#include <vector>
#include <initializer_list>

class Test
{
public:
    Test(const Test & t) : v(t.v) {
        std::cout << "Copy Cons" << std::endl;
    }
    Test(Test && t) : v(std::move(t.v)) {
        std::cout << "MC" << std::endl;
    }
    Test(int val) : v(val) {}
private:
    int v;
};

int main()
{
    std::vector<Test> vv({Test(0), Test(1), Test(2)});

    return 0;
}//main

It's output:

Copy Cons
Copy Cons
Copy Cons
Community
  • 1
  • 1
Adam
  • 91
  • 4
  • 3
    `initializer_list` is a pair of pointers. Copying it is very cheap and does not involve any copies of your own type. The issue here is of a different nature. http://stackoverflow.com/questions/8193102/initializer-list-and-move-semantics – R. Martinho Fernandes Nov 28 '12 at 12:11
  • Please look at my test file and the output, and you may see that it's really doing the Copy construction. – Adam Nov 28 '12 at 12:34
  • 1
    Please look at the question I linked to, and you may see that the reason for that does not have anything to do with passing the `initializer_list` by value. – R. Martinho Fernandes Nov 28 '12 at 12:50

1 Answers1

3

If you look closely at the link provided in the first comment, you will see why the copy happens:

  1. When you define an initializer_list, the compiler stuffs the content of that list somewhere into a chunk of memory. The initializer_list then consists only of two pointers to the begin and end of that chunk of memory.
  2. When the list is copied into the constructor, only the pointers are copied.
  3. When the vector has allocated its own memory, it copies your objects from the list's chunk'o'mem into it's own memory. That's where you see the copy ctor, not when the list itself is copied.

You can see the syntactic element named initializer lis, i.e. curly braces and a list of comma separated values, as an instruction for the compiler to put the content of that list into a read-only chunk of memory. The std::initializer_list is nothing more than a pair of iterators to that chunk.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • Thanks! I acutually have read that post, but unfortunately did not understand it. I'm a new guy on cpp and I'm endeavoring on reading the STL source code. Cause c++-11 is new and not much stuff is on that, so I may just have made some silly mistakes. – Adam Nov 28 '12 at 15:26
  • The original proposal by Stroustrup and dos Reis is very good at explaining how a model compiler would implement `initializer_list` as a proxy for an implicit array, why the elements thereof are `const` to facilitate various optimisations, etc.: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2100.pdf – underscore_d Jun 26 '16 at 00:43