C++ 返回std::vector时未调用复制构造函数

C++ 返回std::vector时未调用复制构造函数,c++,c++11,stdvector,C++,C++11,Stdvector,我想知道这里发生了什么: class Test { public: Test() { std::cout << "Constructor" << std::endl; } Test(const Test &) { std::cout << "Copy" << std::endl; } Test(const Test &&) { std::cout << "Move" << st

我想知道这里发生了什么:

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;
}
人们可以用省略来解释第一个案例。但这与第二种情况相反,在第二种情况下调用了move构造函数

另一种解释是,函数中的std::vector释放其内容并将其传递给第二个std::vector,因此不需要调用复制构造函数。但第三个案例表明,事实并非如此

那么,这里发生了什么?或者这只是一个混乱的编译器优化?

第一种情况(最坏情况下)移动向量(因此只传输内部指针,而不复制/移动
Test

第三种情况是复制vector,您必须执行以下操作来移动它,而不是复制:

{
    std::vector<Test> TestVektor(1);
    std::vector<Test> TestVektor2 = std::move(TestVektor);
}
{
std::向量TestVektor(1);
std::vector TestVektor 2=std::move(TestVektor);
}
人们可以用省略来解释第一个案例

TestVektor
是根据从
getTestVektor
返回的临时向量构建的。一个、两个或两个举措都可能被忽略

但这与第二种情况相反,在第二种情况下调用了move构造函数

复制/移动省略不是强制性的。它既可以用于从
getTest
返回,也可以用于
TestVarible
的复制初始化,但没有用于其中一个

我测试的GCC和Clang版本都省略了这两个版本

另一种解释是,函数中的std::vector释放其内容并将其传递给第二个std::vector

这正是
std::vector
的move构造函数所做的

但第三种情况是复制赋值,而不是移动构造


总之,这里发生的事情主要是由
std::vector的move构造函数解释的,但第二种情况也显示了复制/移动省略的明显(缺乏)副作用。

Constructor
Destructor

Constructor
Destructor

Constructor
Copy
Destructor
Destructor

为什么VisualStudio会在案例2中调用移动对我来说是个谜。您是否禁用了优化?

熟悉“命名返回值优化”?(我同意它也适用于案例2)您的复制/移动分配操作员在哪里?@BenVoigt Yes。显然,向量的移动构造函数是重要的一点…@xaxxon似乎我的编译器隐式声明了它们…@xaxxon它被更改为/O2并得到了相同的结果;-)
Constructor
Destructor

Constructor
Destructor

Constructor
Copy
Destructor
Destructor