我想知道这里发生了什么:
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,因此不会调用复制构造函数。但第三个案例表明,事实并非如此。
那么,这里发生了什么?或者这只是简单的编译器opitimization?
答案 0 :(得分:2)
第一种情况(最坏情况下)移动向量(因此只传输内部指针,而不复制/移动Test
)。
第3个案例制作了vector的副本,你必须执行以下操作来移动它而不是复制:
{
std::vector<Test> TestVektor(1);
std::vector<Test> TestVektor2 = std::move(TestVektor);
}
答案 1 :(得分:0)
可以用复制省略解释第一个案例。
TestVektor
是从getTestVektor
返回的临时向量构造的。其中一个,两个或两个都没有被删除。
但这与第二种情况相反,后者调用了移动构造函数。
复制/移动省略不是强制性的。它可以用于getTest
的返回和TestVarible
的复制初始化,但它没有用于其中一个。
我测试的GCC和Clang的版本都忽略了它们。
另一种解释是,函数中的std :: vector释放其内容并将其传递给第二个std :: vector
这正是std::vector
的移动构造函数所做的。
但第三种情况是复制作业,而不是移动构造。
总之,这里发生的事情主要由std::vector
的移动构造函数解释,但第二个案例也显示了复制/移动省略的可观察(缺乏)副作用。
答案 2 :(得分:0)
FYI来自clang的输出,-O2:
Constructor
Destructor
Constructor
Destructor
Constructor
Copy
Destructor
Destructor
为什么visual studio会调用一个动作,2对我来说是一个谜。你禁用了优化吗?