5

Here is the code:

#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <iomanip>

class Date
{
public:
    Date(int year, int month, int day) : year(year), month(month), day(day) {}
    Date(const Date &d) : year(d.year), month(d.month), day(d.day) {}
    std::string to_string() {
        std::stringstream ss;
        ss << std::setfill('0') << std::setw(4) << year << '-' << std::setw(2) << month << '-' << day;
        return ss.str();
    }
private:
    int year, month, day;
};

int main()
{
    std::vector<Date> vd;
    vd.emplace_back(2017, 1, 13);
    vd.emplace_back(vd[0]);
    std::cout << vd.back().to_string() << "\n";
}

When I compile and run it with VS2015 (compiler 19.00.24215.1), it prints nonsense like 20750440-20709568-13. When I compiled it with g++ 4.8.4, it prints 2017-01-13 as expected. However, if I replace vd.emplace_back(vd[0]) with vd.push_back(Date(vd[0])), it prints 2017-01-13 with both VS2015 and g++.

I previously assumed that vector::emplace_back(args) was functionally equivalent to vector::push_back(Ctor(args)), possibly avoiding a copy? Why do they produce different behavior here? Is this a VS2015 bug?

jcai
  • 3,448
  • 3
  • 21
  • 36
  • 1
    "Is this a VS2015 bug" I'm prepared to bet that yes, it is a bug :) – Rakete1111 Jan 13 '17 at 18:49
  • Pretty sure it is a bug. Trying to find the related Q&A where the rationale is the standard does state this is not allowed. – NathanOliver Jan 13 '17 at 18:50
  • 1
    Found it: http://stackoverflow.com/questions/18788780/is-it-safe-to-push-back-an-element-from-the-same-vector?noredirect=1&lq=1 and http://stackoverflow.com/questions/29300408/is-inserting-an-element-of-a-stdvector-into-the-same-vector-allowed – NathanOliver Jan 13 '17 at 18:52
  • Yes it's a bug: http://stackoverflow.com/a/24909203/3658660 and https://www.reddit.com/r/cpp/comments/vog1p/a_commonly_unknown_stdvector_pitfall/ – hlscalon Jan 13 '17 at 18:53
  • 1
    Also: VS 2017 also prints `2017-01-13` with `emplace_back`. The bug is probably caused by the partial implementation of modern C++ in VS. – Rakete1111 Jan 13 '17 at 18:54
  • Unrelated to your problem, but when you do `vd.push_back(Date(vd[0]))` you are creating *two* copies of the object (not including any copying from a possible vector resize). The first when you create a temporary object with `Date(vd[0])`, then a second copy when the vector copies the (temporary) object into the vector. Doing just `vd.push_back(vd[0])` should work just fine, and with one less copy. – Some programmer dude Jan 13 '17 at 18:55

0 Answers0