复制构造函数的奇怪副作用

问题描述 投票:1回答:1

此简单代码:

#include <iostream>
#include <vector>

struct my_struct
{
    int m_a;

    my_struct(int a) : m_a(a) { std::cout << "normal const " << m_a << std::endl; }

    my_struct(const my_struct&& other) : m_a(other.m_a) { std::cout << "copy move " << other.m_a << std::endl; }

    my_struct(const my_struct &other) : m_a(other.m_a) { std::cout << "copy const " << other.m_a << std::endl; }
};

class my_class
{
public:
    my_class() {}

    void append(my_struct &&m) { m_vec.push_back(m); }

private:
    std::vector<my_struct> m_vec;
};

int main()
{
    my_class m;

    m.append(my_struct(5));
    m.append(std::move(my_struct(6)));
}

产生此输出:

normal const 5
copy const 5
normal const 6
copy const 6
copy const 5

第一次追加请求将创建对象,而push_back将创建一个副本。同样,第二个追加请求创建对象,而push_back创建副本。现在,第一个对象的副本构造函数被神秘地调用。有人可以解释一下会发生什么吗?看起来像是一个奇怪的副作用...

c++
1个回答
0
投票

现在,神秘地调用了第一个对象的副本构造函数。有人可以解释一下会发生什么吗?看起来像是一个奇怪的副作用...

[当您在push_back上调用std::vector时,矢量可能需要增大其大小,如cppreference中所述:

如果新的size()大于Capacity(),则所有迭代器和引用(包括过去的迭代器)都将失效。否则,只有过去的迭代器才无效。

您可以在将任何内容推入向量之前使用reserve。试试这个:

class my_class
{
public:
    my_class()
    {
        m_vec.reserve(10); // Use any number that you want.
    }

    void append(my_struct &&m) { m_vec.push_back(m); }

private:
    std::vector<my_struct> m_vec;
};

[另外,您需要修复move构造函数的签名,因为move构造函数需要rvalue引用(更具体地说,是xvalue或prvalue)。它应该像这样:

my_struct(my_struct&& other) : m_a(other.m_a) { std::cout << "copy move " << other.m_a << std::endl; }
© www.soinside.com 2019 - 2024. All rights reserved.