Spurious copies in c++03 libstdc++ vs c++11

后端 未结 1 1549
悲&欢浪女
悲&欢浪女 2021-01-18 10:37

Consider this code:

#include 
#include 
#include 

using namespace std;

class Foo
{
public:
   Foo() : _x(0) 
   {
         


        
相关标签:
1条回答
  • 2021-01-18 11:32

    This is LWG 334:

    The C++03 Standard mandates the following effects for operator[] ([lib.map.access]p1):

    Returns: (*((insert(make_pair(x, T()))).first)).second.


    libstdc++ implements the insertion used by operator[] (in the case where the key doesn't exist yet) as follows in C++03 mode:

     __i = insert(__i, value_type(__k, mapped_type()));
    

    __i is the insertion point, it is computed as

    iterator __i = lower_bound(__k);
    

    __k is the parameter of operator[].

    The creation of the temporary value_type(__k, mapped_type()) causes the first copy (from mapped_type() into the value_type pair). The second copy is the result of insert, which copies the value_type pair into an actual node.

    The original version from 1997 is:

    return (*((insert(value_type(k, T()))).first)).second;
    

    which is almost to the letter of the Standard (which didn't even exist back then!). The last time it was changed significantly was in 1998. Prior to that, it used:

    __i = insert(__i, value_type(__k, _Tp()));
    

    The commit message says this was to

    Update to SGI STL 3.11.


    Earlier versions of the SGI STL (1995) did indeed specify map::operator[] in the same way as the C++03 Standard:

    For a map m and key k, m[k] is semantically equivalent to (*((m.insert(make_pair(k, T()))).first)).second .

    SGI STL v2.03 (1997) had already switched to using value_type instead of make_pair. And as gcc's commit log suggests, SGI STL's implementation changed again between v3.0 (also 1997) and v3.11 (1998) from insert(value_type(.. to the form still present in libstdc++ using lower_bound and only creating the pair if the key doesn't exist yet.


    So one could say that libstdc++ implements the first proposed resolution of LWG 334 (value_type instead of make_pair). This isn't exactly what happened, though, looking at its history. It's simply following SGI STL. libc++ doesn't strictly conform to C++03 in this respect.


    libstdc++'s C++11 version of the same operator uses a custom emplacement function. The C++11 Standard's specification of map::operator[] follows the proposed resolution of LWG 334:

    Effects: If there is no key equivalent to x in the map, inserts value_type(x, T()) into the map.

    (where x is the parameter of operator[])

    0 讨论(0)
提交回复
热议问题