将空初始化列表分配给现有向量或映射的效果?

时间:2017-06-08 16:44:45

标签: c++ c++11

我有2个容器,a std::vectorstd::map

vector<int> my_vector;
map<string,int> my_map;
my_vector.push_back(3);

// elaboration of my_vector;
...

my_map["Hello"] = 1;

// elaboration of my_map
...

后来我做了:

my_map = {};
my_vector = {};

这应该使2个容器2个空容器,对吗?此外,先前从my_mapmy_vector指出的内存会发生什么?

(我在C ++ 11上)

2 个答案:

答案 0 :(得分:3)

是的,两个分配都会导致向量和地图被清空。这两个赋值都是向量和映射的大小是线性的,因为它们都要求在赋值之前销毁容器中的每个元素,这需要进行O(n)遍历。向量重用内存(https://wandbox.org/permlink/eIJEcEqERC2ybAjU)我认为地图重用内存是否是实现定义的(或者至少我无法从文档中得出)

至于棘手的部分(在我看来),这里调用了哪个赋值运算符?它是来自初始化列表的赋值运算符还是向量和映射的移动赋值运算符(因为{}可以隐式转换为其中一个的实例)。我在cppreference http://en.cppreference.com/w/cpp/language/operator_assignment#Builtin_direct_assignment

找到了这句话
  

请注意,如果某个非类类型的非模板赋值运算符可用,则优先于E1 = {}中的复制/移动赋值,因为{}到非类是一个标识转换,它超出了用户定义的从{}到类类型的转换。

所以如果有一个非模板赋值运算符,std::vector确实有。这比模板std::intializer_list赋值运算符的赋值运算符更受欢迎。您只需检查界面即可查看正在发生的事情。你可以在这里看到相同的

#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>
#include <map>

using std::cout;
using std::endl;
using std::string;

class Something {
public:
    Something() {
        cout << __PRETTY_FUNCTION__ << endl;
    }
    template <typename U>
    Something(std::initializer_list<U>) {
        cout << __PRETTY_FUNCTION__ << endl;
    }
    Something& operator=(const Something&) {
        cout << __PRETTY_FUNCTION__ << endl;
        return *this;
    }
    Something& operator=(Something&&) {
        cout << __PRETTY_FUNCTION__ << endl;
        return *this;
    }
    Something(const Something&) {
        cout << __PRETTY_FUNCTION__ << endl;
    }
    Something(Something&&) {
        cout << __PRETTY_FUNCTION__ << endl;
    }
    template <typename U>
    Something& operator=(std::initializer_list<U>) {
        cout << __PRETTY_FUNCTION__ << endl;
        return *this;
    }

    // to silence unused variable warning
    int get_something() {
        return this->something;
    }
private:
    int something{1};
};

int main() {
    auto something = Something{};
    something = {};
    something = {1, 2, 3};
}

此输出为

Something::Something()
Something::Something()
Something &Something::operator=(Something &&)
Something &Something::operator=(std::initializer_list<U>) [U = int]

请注意,上述情况不是std::vector发生的情况,因为其initializer_list赋值运算符不是模板,因此会调用它。

答案 1 :(得分:1)

两个运算符都将初始化列表中的值复制到容器中,如下所述。由于初始化列表为空,因此在复制分配后,您的集合将为空。

http://www.cplusplus.com/reference/vector/vector/operator=/ http://www.cplusplus.com/reference/map/map/operator=/

您的旧地图和矢量会被其复制分配运算符破坏。 &#34;在调用之前存储在容器中的元素被分配或销毁&#34;,如本帖子的评论所述。