The push_back function that I implemented:
void push_back(T& num) {
my_vec[index] = num;
index++;
}
And the emplace_back function:
template<class... Args>
void emplace_back(Args&&... args) {
push_back(T(std::forward<Args>(args)...));
}
Do you see any problem with this? If yes then could you please tell me
Also, please let me know how does this work?
Please note: the emplace_back is not my implementation, I took it from other questions as I was looking for a way to implement my own emplace_back.
Do you see any problem with this?
You aren't really emplacing with this. There's still an assignment.
std::vector<T>
doesn't allocate an array of T
. It allocates raw memory with the size and alignment of an array of T
, and then instantiates objects in that raw memory.
With that in mind, you should probably implement push_back
in terms of emplace_back
, rather than the other way around.
template <typename T>
class my_vector {
T * start;
std::size_t size;
std::size_t capacity;
void grow(); // Implementation of this is left as an exercise to the reader
public:
template <typename... Args>
reference emplace_back(Args&&... args) {
if (size == capacity) grow();
return *new (start + size++) T(std::forward<Args>(args)...);
}
reference push_back(const T & t) { return emplace_back(t); }
reference push_back(T && t) { return emplace_back(std::move(t)); }
}
Also, please let me know how does this work?
template <typename... Args>
allows zero or more types to match this template, and then T(std::forward<Args>(args)...)
is constructing a T
with those arguments, "perfectly forwarding" them, ie rvalues are passed as rvalues and lvalues as lvalues.
Nb because std::vector
doesn't new[]
, you cannot implement something that behaves exactly like std::vector
before C++ 20, because it has to be able to return a pointer to an array of T
from data
without constructing an array of T
.
The point of emplace_back
is to construct an object in place. Your implementation constructs an object then copies it to my_vec
.
Your implementation will not work with types that are not copyable. Eg this won't compile:
Vector<std::thread> v;
v.emplace_back([](){});
v.push_back(std::thread([](){}));
Changing push_back
to take it's argument via rvalue reference will fix the issue:
void push_back(T&& num) {
my_vec[index] = std::move(num);
index++;
}
template<class... Args>
void emplace_back(Args&&... args) {
push_back(T(std::forward<Args>(args)...));
}
I think however that most standard library implementations are implemented using emplace_back
as the lowest level function:
void push_back(T&& num) {
emplace_back(std::move(num));
}
template<class... Args>
void emplace_back(Args&&... args) {
my_vec[index] = T(std::forward<Args>(args)...);
index++;
}
This then makes it easier to implement the push_back
overload that copies the values:
void push_back(const T& num) {
emplace_back(num);
}
Note that this implementation is using move assignment which is still not quite the intention of emplace_back
which requires constructing an object in place using placement new on uninitialised memory but assuming my_vec
is an array of objects or similar its the best you can do (without fully implementing the semantics of std::vector
which is fairly complex).
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.