简体   繁体   中英

move assignment not called for vector element

I am new to c++11 and I am trying to experiment with move semantics and rvalue function parameters. I do not understand why the following code won't compile:

class MatchEntry
{
  unique_ptr<char []> key;

public:
  MatchEntry() {}

  MatchEntry(const char *key_bytes, int key_nbytes) {
    char *data = new char[key_nbytes];
    copy(key_bytes, key_bytes + key_nbytes, data);
    key = unique_ptr<char []>(data);
  }

};

void add_entry(vector<MatchEntry> v, MatchEntry&& e, int index) {
  v[index] = e;
}

class MatchEntry has a unique_ptr member and therefore no implicit copy assignment operator can be generated by the compiler. However a move assignment operator is generated. The add_entry function takes a rvalue reference to a MatchEntry and therefore I expected the move assignment to be called. But I get the following error when I try to compile:

gg.cpp: In function ‘void add_entry(std::vector<MatchEntry>, MatchEntry&&, int)’:
gg.cpp:57:12: error: use of deleted function ‘MatchEntry& MatchEntry::operator=(const MatchEntry&)’
   v[index] = e;
            ^
gg.cpp:32:7: note: ‘MatchEntry& MatchEntry::operator=(const MatchEntry&)’ is implicitly deleted because the default definition would be ill-formed:
 class MatchEntry
       ^
gg.cpp:32:7: error: use of deleted function ‘std::unique_ptr<_Tp [], _Dp>& std::unique_ptr<_Tp [], _Dp>::operator=(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = char; _Dp = std::default_delete<char []>]’
In file included from /usr/include/c++/4.9/memory:81:0,
                 from gg.cpp:1:
/usr/include/c++/4.9/bits/unique_ptr.h:599:19: note: declared here
       unique_ptr& operator=(const unique_ptr&) = delete;

Before directly discussing the compilation error, you should definitely take v by reference in this fuction.

void add_entry(vector<MatchEntry> &v, MatchEntry&& e, int index) {
                         //       |
                         //       `--- by reference here
  v.at(index) = std::move(e);
}

Anyway, the problem is the e is an lvalue, and therefore the assignment was trying to use copy assignment instead of move assignment. A named variable is always an lvalue, regardless of whether its type is MatchEntry or MatchEntry& or MatchEntry&& . Of course, we know that the object referenced by e was an rvalue, and therefore we can use move to tell the compiler to treat e as an rvalue.

(Unrelated: but I always like to access vectors with .at(index) . It's safer due to the bounds-checking.)

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