将空向量传递给对象的“正确”方法是什么?

时间:2012-04-05 09:18:08

标签: c++ stl stdvector assignment-operator pass-by-const-reference

我正在开发一个相当大的C ++项目,遗憾的是它并没有真正充分利用C ++。代码的大部分仍然是纯粹的C包裹在荒谬的C ++类中。

因此,我尝试通过引入一些C ++和STL来使代码更具可读性和更安全性。

然而,当我将一个向量分配给一个对象成员时,我得到一个奇怪的崩溃(确切地说是调试错误)。想象一下:

class A
{

public:

    // Default constructor
    A()
    {
        initialize(std::vector<unsigned long>());
    };

    A(const std::vector<unsigned long> &data)
    {
        initialize(data)
    };

    ~A() {};

    void initialize(const std::vector<unsigned long> &data)
    {
        m_data = data;
    };

private:

    std::vector<unsigned long> m_data;

};

然后在代码中的其他地方,我打电话:

a.initialize(std::vector<unsigned long>());

但是,程序会终止调试错误:矢量迭代器不兼容。 它发生在这个任务上:

m_data = data;

......应该制作副本,这是我打算做的。

但是,如果我将此行更改为:

m_data = std::vector<unsigned long>(data);

......一切都按预期工作。

我的问题是:为什么?这是使用空向量初始化对象的正确方法吗?

请记住,实际中的类要大得多,并且传递的成员要多得多,这就是我使用初始化函数的原因。并且还有可能传递已经存在的数组,因此我需要能够将其初始化为空或使用现有数据。

编辑:我找到了崩溃的原因。我发现我正在查看的代码实际上有点不同:

A *pA = malloc(...); // Not really malloc but a wrapper for a WINAPI-Alloc
// Some stuff happens in between
pA->initialize(std::vector<unsigned long>());

实际上,A的构造函数从未被调用过,因此向量成员(m_data)的构造函数也从未执行过。这就是为什么在隐式调用复制函数崩溃时分配构造函数的原因,因为目标向量尚未构造。好的经验教训和更可怕的代码改进:)

谢谢!

3 个答案:

答案 0 :(得分:3)

我不知道为什么你的代码崩溃了,因为它看起来不错,表面上看起来不错。也许您应该修改问题以包含minimal test case

但是,有更好的方法可以进行初始化:

class A
{
public:

    // Default constructor.
    // Relies on the fact that the default constructor for std::vector is
    // an empty vector.
    A()
    {}

    // Use the initialisation list.
    A(const std::vector<unsigned long> &data)
    : m_data(data)
    {}

private:
    std::vector<unsigned long> m_data;
};

答案 1 :(得分:1)

std::vector构造函数已经初始化了一个空向量。 如果要从另一个std :: vector分配数据,可以使用复制构造函数。

class A
{

public:

    // Default constructor
    A()
    {
        // Not required:
        // initialize(std::vector<unsigned long>());
    }

    // Make it explicit
    explicit A(const std::vector<unsigned long> &data)
      : m_data(data) // vector copy ctor
    {
    }

    ~A() {}


private:

    std::vector<unsigned long> m_data;

};

答案 2 :(得分:0)

是电话:

a.initialize(std::vector<unsigned long>());

在与定义A的库不同的库中?在这种情况下,我猜其中一个库是在启用调试迭代器的情况下构建的,而另一个库则不是。