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

2021-05-02 13:37:55 +08:00
 wisefree
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;
}

2078 次点击
所在节点    C++
16 条回复
edimetia3d
2021-05-02 13:50:21 +08:00
没必要关注这种 case, 八成是编译器把初始化优化了.
leimao
2021-05-02 13:54:41 +08:00
当 argument 是 lvalue 的时候,invoke copy constructor; 当 argument 是 rvalue 的时候,invoke move constructor;。
https://leimao.github.io/blog/CPP-lvalue-rvalue-Reference/
leimao
2021-05-02 14:00:04 +08:00
确切的说应该叫 lvalue reference 和 rvalue reference 。
wisefree
2021-05-02 14:03:30 +08:00
@edimetia3d 我也感觉是被优化了,所以关闭了优化,但是没有应有的效果。有其他的思路么?
wisefree
2021-05-02 14:03:55 +08:00
@leimao 问题是为什么没有 invoke 成功?
leimao
2021-05-02 14:14:02 +08:00
@wisefree 我想你问的应该是为什么 Complex c{ Complex{1, 2} };没有 invoke copy constructor ?
leimao
2021-05-02 14:37:42 +08:00
@leimao 我跑了一下程序看了下结果想了想,一楼应该是对的。估计编译器把
```
Complex c{ Complex{1, 2} };
```
优化成了
```
Complex c{ 1, 2 };
```
所以你啥也没 print 出来。
leimao
2021-05-02 14:46:15 +08:00
@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
2021-05-02 15:08:49 +08:00
你需要关闭 constructor elision
g++ -fno-elide-constructors --std=c++11 ....

在 c++17 之后你例子里的代码会被 guaranteed copy elision 保证干掉,所以就算加了这个参数也没用,因为已经不是优化而是标准之一了。在此之前都是编译器自己的 constructor elision 在作用。
lcdtyph
2021-05-02 15:11:26 +08:00
msvc 我不会用,不知道对应的选项是什么- -
qieqie
2021-05-02 15:42:08 +08:00
copy elision
wisefree
2021-05-02 21:48:09 +08:00
@leimao 感谢
wisefree
2021-05-02 21:49:16 +08:00
@lcdtyph 用了这个参数,确实可以,厉害了!
wisefree
2021-05-02 21:49:31 +08:00
@qieqie 谢啦
jones2000
2021-05-03 19:01:08 +08:00
你这个要完成什么功能? 用最简单的语法完成你想要功能不就可以了. 怎么高深的语法, 有几个人会用呀?
shrikextl
2021-06-14 20:28:39 +08:00
纠结这个干啥,移动构造又不是给你做这种构造写法的,想测试移动构造函数的方法多的很

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/774622

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX