Visual 2019 中的 Copy Elision
Copy Elision in visual 2019
我试图测试一个小代码来检查我的编译器(在 Visual Studio 2019 下)是否复制省略,因为它在 C++17 下的某些情况下不再是可选的。
所以我尝试了下面的代码:
#include <iostream>
#include <vector>
using namespace std;
struct myStruct
{
myStruct() { cout << "default ctor" << endl; }
myStruct(const myStruct& str) { cout << "copy ctor" << endl; }
myStruct& operator=(myStruct other) { cout << "Copy assignement" << endl; return *this; }
myStruct(myStruct&& str) noexcept { cout << "move ctor" << endl; }
myStruct& operator=(myStruct&& other) { cout << "move assignement" << endl; return *this; }
~myStruct() { cout << "deleted" << endl; }
};
myStruct get()
{
myStruct s;
return s;
}
int main()
{
vector<myStruct> vect;
vect.reserve(10);
cout << "Creating The Vector" << endl;
vect.push_back(get());
vect.push_back(get());
cout << "Cretion End" << endl;
return 0;
}
据我所知,调用函数 get() 将触发 RVO,因此我将仅获得 ctor 调用。但是当我 运行 我得到的程序时(我在调用 get() 函数后在与复制相关的行前面添加了 <<<< ):
Creating The Vector
default ctor
move ctor
deleted
move ctor <<<<
deleted <<<<
default ctor
move ctor
deleted
move ctor <<<<
deleted <<<<
Cretion End
deleted
deleted
尝试使用 gcc 时,我得到:
Creating The Vector
default ctor
move ctor
deleted
default ctor
move ctor
deleted
Cretion End
deleted
deleted
看来微软还是没有实现Copy elision,还是我的代码有问题让我错过了Copy elision的真正魅力?
提前致谢
None 本例中的副本需要被任何(当前存在的)C++ 版本删除。标准规定了几个拷贝:从s
拷贝到get
的return值对象,从引用参数拷贝到push_back
到vector
] 的内部对象。后一个副本不能被省略,前一个副本的省略也不一定会发生。
如果您谈论的是 C++17 的保证省略,这仅适用于使用纯右值来初始化(该类型的)对象。这在此处从未发生过(在传递给调用 push_back
的临时参数之外,但这对于任何版本的 C++ 都是正常的),因此它不适用。
这里有一个简单的测试:如果假设副本的源对象有一个变量名,则省略(如果适用)不是强制性的。
我试图测试一个小代码来检查我的编译器(在 Visual Studio 2019 下)是否复制省略,因为它在 C++17 下的某些情况下不再是可选的。
所以我尝试了下面的代码:
#include <iostream>
#include <vector>
using namespace std;
struct myStruct
{
myStruct() { cout << "default ctor" << endl; }
myStruct(const myStruct& str) { cout << "copy ctor" << endl; }
myStruct& operator=(myStruct other) { cout << "Copy assignement" << endl; return *this; }
myStruct(myStruct&& str) noexcept { cout << "move ctor" << endl; }
myStruct& operator=(myStruct&& other) { cout << "move assignement" << endl; return *this; }
~myStruct() { cout << "deleted" << endl; }
};
myStruct get()
{
myStruct s;
return s;
}
int main()
{
vector<myStruct> vect;
vect.reserve(10);
cout << "Creating The Vector" << endl;
vect.push_back(get());
vect.push_back(get());
cout << "Cretion End" << endl;
return 0;
}
据我所知,调用函数 get() 将触发 RVO,因此我将仅获得 ctor 调用。但是当我 运行 我得到的程序时(我在调用 get() 函数后在与复制相关的行前面添加了 <<<< ):
Creating The Vector
default ctor
move ctor
deleted
move ctor <<<<
deleted <<<<
default ctor
move ctor
deleted
move ctor <<<<
deleted <<<<
Cretion End
deleted
deleted
尝试使用 gcc 时,我得到:
Creating The Vector
default ctor
move ctor
deleted
default ctor
move ctor
deleted
Cretion End
deleted
deleted
看来微软还是没有实现Copy elision,还是我的代码有问题让我错过了Copy elision的真正魅力?
提前致谢
None 本例中的副本需要被任何(当前存在的)C++ 版本删除。标准规定了几个拷贝:从s
拷贝到get
的return值对象,从引用参数拷贝到push_back
到vector
] 的内部对象。后一个副本不能被省略,前一个副本的省略也不一定会发生。
如果您谈论的是 C++17 的保证省略,这仅适用于使用纯右值来初始化(该类型的)对象。这在此处从未发生过(在传递给调用 push_back
的临时参数之外,但这对于任何版本的 C++ 都是正常的),因此它不适用。
这里有一个简单的测试:如果假设副本的源对象有一个变量名,则省略(如果适用)不是强制性的。