返回 std::vector 时未调用复制构造函数
copy constructor not called when returning a std::vector
我想知道这里发生了什么:
class Test {
public:
Test() { std::cout << "Constructor" << std::endl; }
Test(const Test &) { std::cout << "Copy" << std::endl; }
Test(const Test &&) { std::cout << "Move" << std::endl; }
~Test() { std::cout << "Destructor" << std::endl; }
};
std::vector<Test> getTestVektor() {
std::vector<Test> TestVektor(1);
return TestVektor;
}
Test getTest() {
Test TestVariable;
return TestVariable;
}
int main() {
{
std::vector<Test> TestVektor = getTestVektor();
}
std::cout << std::endl;
{
Test TestVarible = getTest();
}
std::cout << std::endl;
{
std::vector<Test> TestVektor(1);
std::vector<Test> TestVektor2 = TestVektor;
}
return 0;
}
使用 VisualStudio 2012 编译:
Constructor
Destructor
Constructor
Move
Destructor
Destructor
Constructor
Copy
Destructor
Destructor
第一种情况可以用复制省略来解释。但这与调用移动构造函数的第二种情况相反。
另一种解释是,函数中的std::vector将其内容释放并传递给第二个std::vector,因此没有调用复制构造函数。但是第三个案例表明,事实并非如此。
那么,这里发生了什么?或者这只是疯狂的编译器优化?
第一种情况(在最坏的情况下)移动向量(因此只传输内部指针,没有Test
的copy/move)。
第 3 种情况复制 vector,您必须执行以下操作来移动它而不是复制:
{
std::vector<Test> TestVektor(1);
std::vector<Test> TestVektor2 = std::move(TestVektor);
}
One could explain the first case with copy elision.
TestVektor
是从 return 从 getTestVektor
编辑的临时向量构建的移动。一个、两个或一个都没有被省略。
But that's contrary to the second case, where the move constructor was called.
Copy/move 省略不是强制性的。它可以用于 getTest
的 return 和 TestVarible
的复制初始化,但它没有用于其中之一。
我测试的 GCC 和 Clang 版本都被省略了。
Another explanation would be, that the std::vector in the function releases its contents and passes it to the second std::vector
这正是 std::vector
的移动构造函数所做的。
但是第三种情况是复制赋值,而不是移动构造。
总之,这里发生的事情主要由 std::vector
的移动构造函数解释,但第二种情况也显示了 copy/move 省略的可观察(缺乏)副作用。
仅供参考,来自 clang 的输出,带有 -O2:
Constructor
Destructor
Constructor
Destructor
Constructor
Copy
Destructor
Destructor
为什么 visual studio 会在情况 2 中调用移动对我来说是个谜。您是否禁用了优化?
我想知道这里发生了什么:
class Test {
public:
Test() { std::cout << "Constructor" << std::endl; }
Test(const Test &) { std::cout << "Copy" << std::endl; }
Test(const Test &&) { std::cout << "Move" << std::endl; }
~Test() { std::cout << "Destructor" << std::endl; }
};
std::vector<Test> getTestVektor() {
std::vector<Test> TestVektor(1);
return TestVektor;
}
Test getTest() {
Test TestVariable;
return TestVariable;
}
int main() {
{
std::vector<Test> TestVektor = getTestVektor();
}
std::cout << std::endl;
{
Test TestVarible = getTest();
}
std::cout << std::endl;
{
std::vector<Test> TestVektor(1);
std::vector<Test> TestVektor2 = TestVektor;
}
return 0;
}
使用 VisualStudio 2012 编译:
Constructor
Destructor
Constructor
Move
Destructor
Destructor
Constructor
Copy
Destructor
Destructor
第一种情况可以用复制省略来解释。但这与调用移动构造函数的第二种情况相反。
另一种解释是,函数中的std::vector将其内容释放并传递给第二个std::vector,因此没有调用复制构造函数。但是第三个案例表明,事实并非如此。
那么,这里发生了什么?或者这只是疯狂的编译器优化?
第一种情况(在最坏的情况下)移动向量(因此只传输内部指针,没有Test
的copy/move)。
第 3 种情况复制 vector,您必须执行以下操作来移动它而不是复制:
{
std::vector<Test> TestVektor(1);
std::vector<Test> TestVektor2 = std::move(TestVektor);
}
One could explain the first case with copy elision.
TestVektor
是从 return 从 getTestVektor
编辑的临时向量构建的移动。一个、两个或一个都没有被省略。
But that's contrary to the second case, where the move constructor was called.
Copy/move 省略不是强制性的。它可以用于 getTest
的 return 和 TestVarible
的复制初始化,但它没有用于其中之一。
我测试的 GCC 和 Clang 版本都被省略了。
Another explanation would be, that the std::vector in the function releases its contents and passes it to the second std::vector
这正是 std::vector
的移动构造函数所做的。
但是第三种情况是复制赋值,而不是移动构造。
总之,这里发生的事情主要由 std::vector
的移动构造函数解释,但第二种情况也显示了 copy/move 省略的可观察(缺乏)副作用。
仅供参考,来自 clang 的输出,带有 -O2:
Constructor
Destructor
Constructor
Destructor
Constructor
Copy
Destructor
Destructor
为什么 visual studio 会在情况 2 中调用移动对我来说是个谜。您是否禁用了优化?