将r值引用传递给构造函数以减少副本

时间:2018-10-04 06:26:30

标签: c++ reference

我有以下代码行

#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 :(得分:1)

您的代码不会编译,但是在进行了编译所需的更改之后,它什么也不做,因为没有使用任何值而被编译到该x86程序集中:

main:
  xor eax, eax
  ret

https://godbolt.org/z/q70EMb

修改代码,使其需要_val成员变量的输出(带有打印语句)表明,通过优化,它只需将值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可能占用相同的内存量。

答案 1 :(得分:0)

您只是分配一个值,而不是复制。但是,您可以在类中拥有一个静态成员,每次调用此方法时,该成员都会增加!

class A
{

    public: // member functions
        static int counter = 0;
        explicit A(int && Val)
        {
            _val = std::move(Val); // \2\
            counter++;
        }
        ....