我想了解 Vector 或 UnorderedMap 的复制赋值运算符后面指定的语义。是否在某处说明了此操作将执行什么操作(或者是实现定义的)? IE。是否会触发存储数据的副本分配或?简单的程序表明,在复制分配的情况下,STL 似乎会进行复制构造+旧条目的销毁。 示例:
#include <iostream>
#include <array>
#include <bitset>
#include <vector>
#include <unordered_map>
using namespace std;
struct TypeA {
TypeA() {
}
TypeA(const TypeA& a)
{
std::cout << "Copy ctor " <<std::endl;
}
TypeA(TypeA&& a)
{
std::cout << "move ctor " <<std::endl;
}
TypeA& operator=(const TypeA& a)
{
std::cout << "Copy assigment " <<std::endl;
return *this;
}
TypeA& operator=( TypeA&& a)
{
std::cout << "move assigment " <<std::endl;
return *this;
}
~ TypeA() {
std::cout << "dtor" << std::endl;
}
};
int main()
{
std::vector<TypeA> bla;
bla.emplace_back(TypeA{});
bla.emplace_back(TypeA{});
bla.emplace_back(TypeA{});
std::vector<TypeA> bla2;
bla2.emplace_back(TypeA{});
bla2.emplace_back(TypeA{});
std::cout << "Start TEST" <<std::endl;
bla2 = bla;
std::cout << "END TEST" <<std::endl;
return 0;
}
结果
...
Start TEST
Copy ctor
Copy ctor
Copy ctor
dtor
dtor
...
END TEST
根据定义,复制赋值运算符将内容替换为源对象内容的副本。
具体来说,如果
std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment
是 true
并且 std::allocator_traits<allocator_type>::is_aleays_equal
是 false
,则目标分配器将替换为源分配器的副本。如果目标分配器和源分配器不相等,则使用目标分配器释放内存,然后在复制元素之前使用源分配器获取内存。否则,目标容器拥有的内存可能会在可能的情况下被重用。
您在测试中遇到的行为是由于对“内存可能会被重用”这句话的误解而导致的,这表明当从源容器复制的元素数量大于要复制的元素数量时,可能需要重新分配内存。目标容器的容量,而其他容器可能有更严格的规则。例如,当负载系数超过其上限时,
std::unordered_map
容器可能需要重新分配。
尽管如此,由于处理增长因子的实现,
bla2
对象的容量一次仅增加一个单位,因此不足以容纳bla
对象的元素。因此,不会发生元素的赋值副本,而是发生在新内存中执行的构造副本,以及在旧内存中实例化的元素的销毁。