Передача r-значения-ссылки конструктору для уменьшения количества копий - PullRequest
0 голосов
/ 04 октября 2018

У меня есть следующие строки кода

#include <stdio.h>
#include <utility>

class A
{
    public: // member functions
        explicit A(int && Val)
        {
            _val = std::move(Val); // \2\
        }
        virtual ~A(){}

    private: // member variables
        int _val = 0;

    private: // member functions
        A(const A &) = delete;
        A& operator = (const A &) = delete;
        A(A &&) = delete;
        A&& operator = (A &&) = delete;
};


int main()
{
    A a01{3}; // \1\
    return 0;
}

Я хотел бы спросить, сколько копий я сделал из \ 1 \ в \ 2 \?Большое спасибо, я заранее ..

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Ваш код не компилируется, но после внесения изменений, необходимых для его компиляции, он ничего не делает и компилируется в эту сборку x86, поскольку ни одно из его значений никогда не используется:

main:
  xor eax, eax
  ret

https://godbolt.org/z/q70EMb

Изменение кода таким образом, чтобы он требовал вывода переменной-члена _val (с оператором print), показывает, что при оптимизации он просто перемещает значение 0x03 в регистр и печатает его:

.LC0:
  .string "%d\n"
main:
  sub rsp, 8
  mov esi, 3
  mov edi, OFFSET FLAT:.LC0
  xor eax, eax
  call printf
  xor eax, eax
  add rsp, 8
  ret

https://godbolt.org/z/JG73Ll

Если вы отключите оптимизацию при попытке заставить компилятор вывести более подробную версию программы:

A::A(int&&):
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov QWORD PTR [rbp-8], rdi
  mov QWORD PTR [rbp-16], rsi
  mov rax, QWORD PTR [rbp-8]
  mov DWORD PTR [rax], 0
  mov rax, QWORD PTR [rbp-16]
  mov rdi, rax
  call std::remove_reference<int&>::type&& std::move<int&>(int&)
  mov edx, DWORD PTR [rax]
  mov rax, QWORD PTR [rbp-8]
  mov DWORD PTR [rax], edx
  nop
  leave
  ret
.LC0:
  .string "%d\n"
main:
  push rbp
  mov rbp, rsp
  sub rsp, 16
  mov DWORD PTR [rbp-4], 3
  lea rdx, [rbp-4]
  lea rax, [rbp-8]
  mov rsi, rdx
  mov rdi, rax
  call A::A(int&&)
  mov eax, DWORD PTR [rbp-8]
  mov esi, eax
  mov edi, OFFSET FLAT:.LC0
  mov eax, 0
  call printf
  mov eax, 0
  leave
  ret
std::remove_reference<int&>::type&& std::move<int&>(int&):
  push rbp
  mov rbp, rsp
  mov QWORD PTR [rbp-8], rdi
  mov rax, QWORD PTR [rbp-8]
  pop rbp
  ret

https://godbolt.org/z/ZTK40d

Ответ на ваш вопрос зависит от того, как ваша программа компилируется и как принудительно выполняется копирование, а также от того, есть ли какая-либо выгода в случае int, чтобы не «копировать» значение, так какint* и int, вероятно, занимают одинаковое количество памяти.

0 голосов
/ 04 октября 2018

Вы просто присваиваете значение, а не копируете.Тем не менее, в вашем классе может быть статический член, который увеличивается каждый раз, когда вызывается этот метод!

class A
{

    public: // member functions
        static int counter = 0;
        explicit A(int && Val)
        {
            _val = std::move(Val); // \2\
            counter++;
        }
        ....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...