Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Requested Survey for VC++ regarding insert and emplace

I am doing a survey of how many special member functions get executed during the following member functions of vector:

insert
emplace
push_back
emplace_back

under various run time conditions. My intent is to publish a paper that will compare these member functions with each other, and on each of the c++11 implementations of the std::lib: libstdc++, libc++, and vc++, and offer advice on when it is best to use each member function (when more than one choice is possible). I have data on libc++ and libstdc++-4.8, but I am lacking data on vc++.

I am looking for answers on vc++ which include the vc++ version number (2010, 2012, 2013). My intent is to give advice on the when each of these members should be preferred, and tempered by real-world experience. I will up-vote the first response for each vc++ version. My intent is not to bash any particular platform. However should my results encourage any existing platform to improve in the future, then that's gravy.

The test I would like to see the results of is:

#include <iostream>
#include <vector>

class X
{
    int i_;
    int* p_;

public:
    struct special
    {
        unsigned c;
        unsigned dt;
        unsigned cc;
        unsigned ca;
        unsigned mc;
        unsigned ma;
    };
    static special sp;

    X(int i, int* p)
        : i_(i)
        , p_(p)
    {
//         std::cout << "X(int i, int* p)\n";
        sp.c++;
    }

    ~X()
    {
//         std::cout << "~X()\n";
        sp.dt++;
    }

    X(const X& x)
        : i_(x.i_)
        , p_(x.p_)
    {
//         std::cout << "X(const X& x)\n";
        sp.cc++;
    }

    X& operator=(const X& x)
    {

        i_ = x.i_;
        p_ = x.p_;
//         std::cout << "X& operator=(const X& x)\n";
        sp.ca++;
        return *this;
    }

    X(X&& x) noexcept
        : i_(x.i_)
        , p_(x.p_)
    {
//         std::cout << "X(X&& x)\n";
        sp.mc++;
    }

    X& operator=(X&& x) noexcept
    {

        i_ = x.i_;
        p_ = x.p_;
//         std::cout << "X& operator=(X&& x)\n";
        sp.ma++;
        return *this;
    }

};

std::ostream&
operator<<(std::ostream& os, X::special const& sp)
{
    os << sp.c << '\n';
    os << sp.dt << '\n';
    os << sp.cc << '\n';
    os << sp.ca << '\n';
    os << sp.mc << '\n';
    os << sp.ma << '\n';
    return os;
}

X::special X::sp{};

int
main()
{
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--insert lvalue no reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace lvalue no reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--insert xvalue no reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace xvalue no reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--insert rvalue no reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--emplace rvalue no reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--insert lvalue reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace lvalue reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--insert xvalue reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace xvalue reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--insert rvalue reallocation--\n";
        X::sp = {};
        v.insert(v.begin(), X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--emplace rvalue reallocation--\n";
        X::sp = {};
        v.emplace(v.begin(), X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }

    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--push_back lvalue no reallocation--\n";
        X::sp = {};
        v.push_back(x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace_back lvalue no reallocation--\n";
        X::sp = {};
        v.emplace_back(x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--push_back xvalue no reallocation--\n";
        X::sp = {};
        v.push_back(std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace_back xvalue no reallocation--\n";
        X::sp = {};
        v.emplace_back(std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--push_back rvalue no reallocation--\n";
        X::sp = {};
        v.push_back(X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(4);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--emplace_back rvalue no reallocation--\n";
        X::sp = {};
        v.emplace_back(X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--push_back lvalue reallocation--\n";
        X::sp = {};
        v.push_back(x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace_back lvalue reallocation--\n";
        X::sp = {};
        v.emplace_back(x);
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--push_back xvalue reallocation--\n";
        X::sp = {};
        v.push_back(std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        X x{0,0};
        std::cout << "--emplace_back xvalue reallocation--\n";
        X::sp = {};
        v.emplace_back(std::move(x));
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--push_back rvalue reallocation--\n";
        X::sp = {};
        v.push_back(X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
    {
        std::vector<X> v;
        v.reserve(3);
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        v.push_back(X(0,0));
        std::cout << "--emplace_back rvalue reallocation--\n";
        X::sp = {};
        v.emplace_back(X{0,0});
        std::cout << X::sp;
        std::cout << "----\n";
    }
}

For example, here is the output of this test on gcc-4.8: https://ideone.com/imAMnU

If someone discovers that the results are different on a gcc version after 4.8 and wants to offer those results, that would also be appreciated (and upvoted). In the event that I am unable to distinguish which equivalent responses came first, I am happy to upvote all of them. However at this time I am uncertain how I will choose a correct answer to this survey.

Contributors of data will surely be gratefully acknowledged in anything I might publish. I am also happy to post a link in this question to any conclusions that might be drawn from this data in the future.

In summary, I realize that this style of question is not the norm for SO. However it is asked in the spirit of furthering public knowledge in the C++ community, and with as much transparency as I can manage. If people want to close this question for whatever reasons, I accept that, but personally do not feel that is in the best interest of the C++ community.

Update

Here is the paper I spoke of that this survey made possible:

insert vs emplace

like image 907
Howard Hinnant Avatar asked Jul 24 '14 04:07

Howard Hinnant


2 Answers

VS2012 Code compiled with Release mode.

Command

cl /O2 /EHsc /W4 Console_12.cpp

Output

--insert lvalue no reallocation--    
4        
4        
1        
3        
4  
0           
----    
--emplace lvalue no reallocation--    
8    
15    
2    
3    
10    
6    
----    
--insert xvalue no reallocation--    
12    
26    
2    
3    
17    
12    
----    
--emplace xvalue no reallocation--    
16    
37    
2    
3    
24    
18    
----    
--insert rvalue no reallocation--    
20    
49    
2    
3    
31    
24    
----    
--emplace rvalue no reallocation--    
24    
60    
2    
3    
38    
30    
----    
--insert lvalue reallocation--    
28    
70    
3    
3    
44    
30    
----    
--emplace lvalue reallocation--    
32    
84    
4    
3    
53    
36    
----    
--insert xvalue reallocation--    
36    
98    
4    
3    
63    
42    
----    
--emplace xvalue reallocation--    
40    
112    
4    
3    
73    
48    
----    
--insert rvalue reallocation--    
44    
127    
4    
3    
83    
54    
----    
--emplace rvalue reallocation--    
48    
141    
4    
3    
93    
60    
----    
--push_back lvalue no reallocation--    
52    
148    
5    
3    
96    
60    
----    
--emplace_back lvalue no reallocation--    
56    
156    
6    
3    
99    
60    
----    
--push_back xvalue no reallocation--    
60    
164    
6    
3    
103    
60    
----    
--emplace_back xvalue no reallocation--    
64    
172    
6    
3    
107    
60    
----    
--push_back rvalue no reallocation--    
68    
181    
6    
3    
111    
60    
----    
--emplace_back rvalue no reallocation--    
72    
189    
6    
3    
115    
60    
----    
--push_back lvalue reallocation--    
76    
199    
7    
3    
121    
60    
----    
--emplace_back lvalue reallocation--    
80    
210    
8    
3    
127    
60    
----    
--push_back xvalue reallocation--    
84    
221    
8    
3    
134    
60    
----    
--emplace_back xvalue reallocation--    
88    
232    
8    
3    
141    
60    
----    
--push_back rvalue reallocation--    
92    
244    
8    
3    
148    
60    
----    
--emplace_back rvalue reallocation--    
96    
255    
8    
3    
155    
60    
----    
like image 122
Jagannath Avatar answered Nov 07 '22 01:11

Jagannath


VS2013

Added #define noexcept which I believe will have been done in the VS2010 and 2012 cases as well.

Release results:

/GS /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Release\vc120.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\Howard.pch" 

--insert lvalue no reallocation--
0
1
1
3
1
0
----
--emplace lvalue no reallocation--
0
3
1
0
3
6
----
--insert xvalue no reallocation--
0
3
0
0
4
6
----
--emplace xvalue no reallocation--
0
3
0
0
4
6
----
--insert rvalue no reallocation--
1
4
0
0
4
6
----
--emplace rvalue no reallocation--
1
4
0
0
4
6
----
--insert lvalue reallocation--
0
3
1
0
3
0
----
--emplace lvalue reallocation--
0
6
1
0
6
6
----
--insert xvalue reallocation--
0
6
0
0
7
6
----
--emplace xvalue reallocation--
0
6
0
0
7
6
----
--insert rvalue reallocation--
1
7
0
0
7
6
----
--emplace rvalue reallocation--
1
7
0
0
7
6
----
--push_back lvalue no reallocation
0
0
1
0
0
0
----
--emplace_back lvalue no reallocat
0
0
1
0
0
0
----
--push_back xvalue no reallocation
0
0
0
0
1
0
----
--emplace_back xvalue no reallocat
0
0
0
0
1
0
----
--push_back rvalue no reallocation
1
1
0
0
1
0
----
--emplace_back rvalue no reallocat
1
1
0
0
1
0
----
--push_back lvalue reallocation--
0
3
1
0
3
0
----
--emplace_back lvalue reallocation
0
3
1
0
3
0
----
--push_back xvalue reallocation--
0
3
0
0
4
0
----
--emplace_back xvalue reallocation
0
3
0
0
4
0
----
--push_back rvalue reallocation--
1
4
0
0
4
0
----
--emplace_back rvalue reallocation
1
4
0
0
4
0
----

Debug results:

/GS /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /sdl /Fd"Debug\vc120.pdb" /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_LIB" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" 

--insert lvalue no reallocation--
0
1
1
3
1
0
----
--emplace lvalue no reallocation-
0
3
1
0
3
6
----
--insert xvalue no reallocation--
0
3
0
0
4
6
----
--emplace xvalue no reallocation-
0
3
0
0
4
6
----
--insert rvalue no reallocation--
1
4
0
0
4
6
----
--emplace rvalue no reallocation-
1
4
0
0
4
6
----
--insert lvalue reallocation--
0
3
1
0
3
0
----
--emplace lvalue reallocation--
0
6
1
0
6
6
----
--insert xvalue reallocation--
0
6
0
0
7
6
----
--emplace xvalue reallocation--
0
6
0
0
7
6
----
--insert rvalue reallocation--
1
7
0
0
7
6
----
--emplace rvalue reallocation--
1
7
0
0
7
6
----
--push_back lvalue no reallocatio
0
0
1
0
0
0
----
--emplace_back lvalue no realloca
0
0
1
0
0
0
----
--push_back xvalue no reallocatio
0
0
0
0
1
0
----
--emplace_back xvalue no realloca
0
0
0
0
1
0
----
--push_back rvalue no reallocatio
1
1
0
0
1
0
----
--emplace_back rvalue no realloca
1
1
0
0
1
0
----
--push_back lvalue reallocation--
0
3
1
0
3
0
----
--emplace_back lvalue reallocatio
0
3
1
0
3
0
----
--push_back xvalue reallocation--
0
3
0
0
4
0
----
--emplace_back xvalue reallocatio
0
3
0
0
4
0
----
--push_back rvalue reallocation--
1
4
0
0
4
0
----
--emplace_back rvalue reallocatio
1
4
0
0
4
0
----
like image 5
MSalters Avatar answered Nov 07 '22 03:11

MSalters