简体   繁体   中英

Effect of assigning an empty initializer list to an existing vector or map?

I have 2 containers, a std::vector and a std::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
...

Later I do:

my_map = {};
my_vector = {};

This should make the 2 containers 2 empty containers, right? Furthermore, what happens to the memory previously pointed to from my_map and my_vector ?

(I'm on C++11)

Yes both assignments cause the vector and the map to be emptied. Both the assignments are linear in the size of the vector and the map because both require every single element in the container to be destroyed before assignment, and that requires an O(n) traversal. The vector reuses memory ( https://wandbox.org/permlink/eIJEcEqERC2ybAjU ) I think whether or not the map reuses memory is implementation defined (or at least I was not able to make out from the documentation)

As for the tricky part (in my opinion), which assignment operator is called here? Is it the assignment operator from an initializer list or the move assignment operator for the vector and the map (since {} is implicitly convertible to an instance of either). I found this quote from cppreference here http://en.cppreference.com/w/cpp/language/operator_assignment#Builtin_direct_assignment

Note that, if a non-template assignment operator from some non-class type is available, it is preferred over the copy/move assignment in E1 = {} because {} to non-class is an identity conversion, which outranks the user-defined conversion from {} to a class type.

So if there is a non template assignment operator, which std::vector does have. That is preferred over the assignment operator from a templated std::intializer_list assignment operator. You just have to inspect the interface to see what is going on. You can see the same here

#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};
}

The output for this is

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

Note that the above situation is not what happens for std::vector because its initializer_list assignment operator is not a template, so that is called.

Both operators copy the values from the initializer list into your container, as referenced below. Since your initializer lists are empty, your collections will be empty after copy-assignment.

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

Your old map and vector are destructed by their copy assign operators. "The elements stored in the container before the call are either assigned to or destroyed", as referenced in the comments to this post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM