I've recently read how std::move can speed up code by just moving the values instead of copying them. So I made a test program to compare the speed using std::vector.
The code:
#include <iostream>
#include <vector>
#include <stdint.h>
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif
#undef max
// Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
// windows and linux.
uint64_t GetTimeMs64()
{
#ifdef _WIN32
    // Windows
    FILETIME ft;
    LARGE_INTEGER li;
    // Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
    // to a LARGE_INTEGER structure.
    GetSystemTimeAsFileTime(&ft);
    li.LowPart = ft.dwLowDateTime;
    li.HighPart = ft.dwHighDateTime;
    uint64_t ret = li.QuadPart;
    ret -= 116444736000000000LL; // Convert from file time to UNIX epoch time.
    ret /= 10000; // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals
    return ret;
#else
    // Linux
    struct timeval tv;
    gettimeofday(&tv, NULL);
    uint64 ret = tv.tv_usec;
    // Convert from micro seconds (10^-6) to milliseconds (10^-3)
    ret /= 1000;
    // Adds the seconds (10^0) after converting them to milliseconds (10^-3)
    ret += (tv.tv_sec * 1000);
    return ret;
#endif
}
static std::vector<std::string> GetVec1()
{
    std::vector<std::string> o(100000, "abcd");
    bool tr = true;
    if (tr)
        return std::move(o);
    return std::move(std::vector<std::string>(100000, "abcd"));
}
static std::vector<std::string> GetVec2()
{
    std::vector<std::string> o(100000, "abcd");
    bool tr = true;
    if (tr)
        return o;
    return std::vector<std::string>(100000, "abcd");
}
int main()
{
    uint64_t timer;
    std::vector<std::string> vec;
    timer = GetTimeMs64();
    for (int i = 0; i < 1000; ++i)
        vec = GetVec1();
    std::cout << GetTimeMs64() - timer << " timer 1(std::move)" << std::endl;
    timer = GetTimeMs64();
    for (int i = 0; i < 1000; ++i)
        vec = GetVec2();
    std::cout << GetTimeMs64() - timer << " timer 2(no move)" << std::endl;
    std::cin.get();
    return 0;
}
I got the following results:
Release (x86) /O2. tr = true
4376 timer 1(std::move)
4191 timer 2(no move)
Release (x86) /O2. tr = false
7311 timer 1(std::move)
7301 timer 2(no move)
The results between the 2 timers are really close and don't really differ that much. I already assumed this is because of Return value optimization (RVO) which means that my returns by value are already moved by the compiler without me knowing, right?
So then I ran new tests without any optimizations to make sure I was right. The results:
Release (x86) /Od. tr = true
40860 timer 1(std::move)
40863 timer 2(no move)
Release (x86) /Od. tr = false
83567 timer 1(std::move)
82075 timer 2(no move)
Now even though the difference between /O2 and /Od is really significant, the difference between no move or std::move (and even between tr being true or false) is minimal.
Does this mean that even though optimizations are disabled, the compiler is allowed to apply RVO or is std::move not as fast as I thought I'd be?
 
     
     
    