V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wisefree
V2EX  ›  C++

C++ 请教关于移动构造函数的问题

  •  
  •   wisefree · 8 天前 · 868 次点击
    Complex c{ Complex{1, 2} };
    

    为什么这条语句不会进入移动构造函数呢?

    1. 用 g++,关闭了优化 g++ -O0 main.cpp

    2. 用 visual studio 2017,也关闭了优化

    #include<iostream>
    
    using std::cout;
    using std::endl;
    
    
    class Complex
    {
    public:
    	Complex(double real, double image) : _real(real), _image(image)
    	{}
    
    	Complex(const Complex& right);
    	Complex(Complex&& right);
    
    	Complex& operator=(const Complex& right);
    	Complex& operator=(Complex&& right);
    
    	virtual ~Complex();
    
    private:
    	double _real {};
    	double _image {};
    };
    
    Complex::Complex(const Complex& right)
    {
        cout << "&" << endl;
        _real = right._real;
        _image = right._image;
    }
    
    
    Complex::Complex(Complex&& right)
    {
        cout << "&&" << endl;
        _real = right._real;
        _image = right._image;
    }
    
    Complex& Complex::operator= (const Complex& right)
    {
    	cout << "= &" << endl;
        if (this != &right)
        {
            _real = right._real;
            _image = right._image;
        }
    
        return *this;
    }
    
    Complex& Complex::operator= (Complex&& right)
    {
    	cout << "= &&" << endl;
        if (this != &right)
        {
            _real = right._real;
            _image = right._image;
        }
    
        return *this;
    }
    
    Complex::~Complex()
    {
        cout << "des" << endl;
    }
    
    
    int main()
    {
    	Complex c{ Complex{1, 2} };
    	//Complex c {std::move(Complex{1, 2})};
    	
    	cout << &c << endl;
    	return 0;
    }
    
    
    15 条回复    2021-05-03 19:01:08 +08:00
    edimetia3d
        1
    edimetia3d   8 天前   ❤️ 1
    没必要关注这种 case, 八成是编译器把初始化优化了.
    leimao
        2
    leimao   8 天前   ❤️ 1
    当 argument 是 lvalue 的时候,invoke copy constructor; 当 argument 是 rvalue 的时候,invoke move constructor;。
    https://leimao.github.io/blog/CPP-lvalue-rvalue-Reference/
    leimao
        3
    leimao   8 天前
    确切的说应该叫 lvalue reference 和 rvalue reference 。
    wisefree
        4
    wisefree   8 天前
    @edimetia3d 我也感觉是被优化了,所以关闭了优化,但是没有应有的效果。有其他的思路么?
    wisefree
        5
    wisefree   8 天前
    @leimao 问题是为什么没有 invoke 成功?
    leimao
        6
    leimao   8 天前
    @wisefree 我想你问的应该是为什么 Complex c{ Complex{1, 2} };没有 invoke copy constructor ?
    leimao
        7
    leimao   8 天前
    @leimao 我跑了一下程序看了下结果想了想,一楼应该是对的。估计编译器把
    ```
    Complex c{ Complex{1, 2} };
    ```
    优化成了
    ```
    Complex c{ 1, 2 };
    ```
    所以你啥也没 print 出来。
    leimao
        8
    leimao   8 天前   ❤️ 1
    @wisefree 个人想法:
    碰到你这种奇怪的没必要的 construction 的方式,`Complex c{ Complex{1, 2} };`,编译器必须把你的语法“优化”(改)成以下两种之一。
    1. `Complex c{1, 2};`
    2. `Complex c_temp{1, 2}; Complex c{c_temp}; `
    不然你这个程序没法运行。
    至于“优化”成 1 还是 2, 可能得看写编译器的人怎么写了。当然估计 100%的人会写 1, 因为 2 这个临时变量是完全没有必要的,浪费资源和 performance 。
    lcdtyph
        9
    lcdtyph   8 天前   ❤️ 3
    你需要关闭 constructor elision
    g++ -fno-elide-constructors --std=c++11 ....

    在 c++17 之后你例子里的代码会被 guaranteed copy elision 保证干掉,所以就算加了这个参数也没用,因为已经不是优化而是标准之一了。在此之前都是编译器自己的 constructor elision 在作用。
    lcdtyph
        10
    lcdtyph   8 天前   ❤️ 1
    msvc 我不会用,不知道对应的选项是什么- -
    qieqie
        11
    qieqie   8 天前   ❤️ 1
    copy elision
    wisefree
        12
    wisefree   8 天前
    @leimao 感谢
    wisefree
        13
    wisefree   8 天前
    @lcdtyph 用了这个参数,确实可以,厉害了!
    wisefree
        14
    wisefree   8 天前
    @qieqie 谢啦
    jones2000
        15
    jones2000   7 天前
    你这个要完成什么功能? 用最简单的语法完成你想要功能不就可以了. 怎么高深的语法, 有几个人会用呀?
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2896 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 01:06 · PVG 09:06 · LAX 18:06 · JFK 21:06
    ♥ Do have faith in what you're doing.