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

时间:2016-04-19 20:59:51

标签: 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" << 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?

3 个答案:

答案 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对我来说是一个谜。你禁用了优化吗?