c 03 libstdc与c 11中的虚假副本
考虑以下代码:
#include <iostream> #include <string> #include <map> using namespace std; class Foo { public: Foo() : _x(0) { cout << "Default" << endl; } Foo(int a) : _x(a) { cout << "Param" << endl; } Foo(Foo const &foo) : _x(foo._x) { cout << "Copy" << endl; } Foo& operator=(Foo const &foo) { cout << "Assignment" << endl; _x = foo._x; return *this; } int get(void) { return _x; } private: int _x; }; int main(int argc,char *argv []) { std::map<int,Foo> foos; Foo a_foo(10); foos[100] = a_foo; return 0; } 使用-std = c 11在gcc中编译并获得输出, Param Default Assignment 删除-std = c 11,然后你得到, Param Default Copy Copy Assignment with c++11 without libc++ example producing the superior output in c++03 mode 这两份额外的副本来自哪里? 它们与调用下标运算符有关,而与调用无关. (如果你删除了作业,它们仍然存在.)对我来说,他们似乎并不需要,即使在前C11世界中,正如libc示例所示. 这最初的动机是看this question 解决方法
这是
LWG 334:
C 03标准要求operator []([lib.map.access] p1)具有以下效果:
libstdc在C03模式下实现operator []使用的插入(在密钥不存在的情况下),如下所示: __i = insert(__i,value_type(__k,mapped_type())); __i是插入点,计算方式为 iterator __i = lower_bound(__k); __k是operator []的参数. 临时value_type(__ k,mapped_type())的创建导致第一个副本(从mapped_type()到value_type对).第二个副本是insert的结果,它将value_type对复制到实际节点中. 1997年的原始版本是: return (*((insert(value_type(k,T()))).first)).second; 这几乎是标准的字母(当时甚至不存在!).它最后一次改变是在1998年.在此之前,它使用了: __i = insert(__i,_Tp())); 提交消息说这是
Earlier versions of the SGI STL (1995)确实以与C 03标准相同的方式指定了map :: operator []:
SGI STL v2.03(1997)已经切换到使用value_type而不是make_pair.正如gcc的提交日志所暗示的那样,SGI STL的实现在v3.0(也是1997)和v3.11(1998)之间再次从insert(value_type(..到使用lower_bound的libstdc中仍存在的形式)再次改变,如果密钥尚不存在. 所以可以说libstdc实现了LWG 334的第一个提议解决方案(value_type而不是make_pair).然而,这并不是发生的事情,看着它的历史.它只是遵循SGI STL.在这方面,libc并不严格遵守C 03. libstdc的同一运算符的C 11版本使用自定义安置功能. C 11标准的map :: operator []规范遵循LWG 334的建议解决方案:
(其中x是operator []的参数) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |