2016-01-22 4 views
1

Я проверил некоторые семантики перемещения после того, как нашел способ для stackoverflow, чтобы измерить прошедшее время в программе, и я хотел бы что-то спросить об этом.Переместить ссылки rvalue указателя

У меня есть два класса А и В и В является производным от А:

class A 
{ 
public: 
    A() 
    { 
     for (int i = 0; i < MAX; i++) 
      str[i] = "~~"; 

     for (int i = 0; i < MAX; i++) 
      flt[i] = i; 
    } 

    std::string str[MAX]; 
    float flt[MAX]; 
}; 

В имеет два конструктора определяется следующим образом:

B(const A*& a) 
{ 
    for (int i = 0; i < MAX; i++) 
     str[i] = a->str[i]; 

    for (int i = 0; i < MAX; i++) 
     flt[i] = a->flt[i]; 
} 



B(A*&& a) 
{ 
    for (int i = 0; i < MAX; i++) 
     str[i] = std::move(a->str[i]); 

    for (int i = 0; i < MAX; i++) 
     flt[i] = std::move(a->flt[i]); 
} 

где MAX = 1000

я заметил, что разница не настолько велика между двумя конструкторами с точки зрения скорости. И если я удалю функцию std::move со второго конструктора, то время, которое я получаю, одинаково от первых. Я ожидаю, что первый конструктор (с ссылкой на константу lvalue как аргумент) скопирует каждый элемент из двух массивов в два массива B, тогда как второй конструктор (с ссылкой на rvalue как аргумент) будет «перемещать» элементы массивов.

история не изменится, если я сравниваю этот

B(A&& a) 
{ 
    for (int i = 0; i < MAX; i++) 
     str[i] = std::move(a.str[i]); 

    for (int i = 0; i < MAX; i++) 
     flt[i] = std::move(a.flt[i]); 
} 

с этим

B(A a) 
{ 
    for (int i = 0; i < MAX; i++) 
     str[i] = a.str[i]; 

    for (int i = 0; i < MAX; i++) 
     flt[i] = a.flt[i]; 
} 

я не имею никакого выигрыша, используя функцию std::move. Я пропустил что-то о семантике перемещения?

+1

Где ваш контрольный код? Компилятор, вероятно, достаточно умный, чтобы полностью исключить копии/хосты. – fredoverflow

+4

Перемещение 'float' - это копия. Перемещение строки 'std :: string' может иметь примерно такую ​​же стоимость, что и копия, если строка невелика или используется некорректная строка COW, предшествующая 5 GCC. –

+0

Я использую это: http://stackoverflow.com/a/21995693/5214404 – Astinog

ответ

3

Как сказал T.C - перемещение поплавка не будет иметь большого значения.

Попробуйте профилирование с чем-то вроде этого:

class A 
{ 
public: 
    A() 
     : strings(new std::string[MAX]) 
     , floats(new float[MAX]) 
    { 
     for (int i = 0; i < MAX; i++) 
      strings[i] = "~~"; 

     for (int i = 0; i < MAX; i++) 
      floats[i] = i; 
    } 

    virtual ~A() 
    { 
     delete[] strings; 
     delete[] floats; 
    } 

    std::string* strings; 
    float* floats; 
}; 

class B : public A 
{ 
public: 
    B(){} 

    B(B&& other) 
    { 
     strings = other.strings; 
     floats = other.floats; 

     other.strings = nullptr; 
     other.floats = nullptr; 
    } 
}; 

int main() 
{ 
    B b; 
    B bb(std::move(b));   
    return 0; 
} 

Как вы можете видеть, что нет петель в ходу конструктора B, мы просто взять внутренностей друга и нуль его, чтобы избежать каких-либо проблем с двойной делецией.

Это, безусловно, НЕ лучший способ упорядочить вышеуказанный код, и его следует использовать только в качестве примера для иллюстрации семантики перемещения.