c – 如何调用std :: vector中包含的对象的构造函数?

当我创建一个对象的std ::向量时,这些对象的构造函数并不总是被调用.
#include <iostream>
#include <vector>
using namespace std;

struct C {
    int id;
    static int n;
    C() { id = n++; }   // not called
//  C() { id = 3; }     // ok,called
};

int C::n = 0;


int main()
{
    vector<C> vc;

    vc.resize(10);

    cout << "C::n = " << C::n << endl;

    for(int i = 0; i < vc.size(); ++i)
        cout << i << ": " << vc[i].id << endl;  
}

这是我得到的输出

C::n = 1
0: 0
1: 0
2: 0
...

这就是我想要的:

C::n = 10
0: 0
1: 1
2: 2
...

在这个例子中,我被迫调整矢量大小,然后手动初始化它的元素?
原因可能是向量的元素没有以有序的方式从第一个到最后一个初始化,所以我不能获得一个确定性的行为?

我想做的是容易地计算在程序中,在不同容器中,在代码的不同点创建的对象的数量,并给每个对象的单个ID.

谢谢!

解决方法

原因是 vector::resize通过调用自动提供的复制构造函数而不是您在示例中定义的构造函数来插入副本.

为了获得所需的输出,您可以明确定义复制构造函数

struct C {
//....
C(const C& other) {
    id = n++;
    // copy other data members
}
//....
};

因为vector :: resize的作用方式(它有一个第二个可选参数,用作其创建的副本的“原型”,在C()的情况下使用认值),这将在您的示例中创建11个对象“原型”和10个副本).

编辑(包括许多意见中的一些好建议):

这个解决方案有几个缺点值得注意,以及一些可能产生更可维护和明智的代码的选项和变体.

>这种方法增加维护成本和风险.每当您添加删除类的成员变量时,都必须记住修改您的副本构造函数.如果您依赖于认的复制构造函数,则不必执行此操作.打击这个问题的一个办法就是将柜台封装在另一个类(like this)中,这也可以说是更好的OO设计,但是当然你还必须牢记the many issues that can crop up with multiple inheritance.
>它可以使其他人更难理解,因为副本不再是大多数人所期望的.类似地,处理您的类(包括标准容器)的其他代码可能会不正当行为.解决这个问题的一个方法是为你的类定义一个operator ==方法(而且may be argued这是一个很好的主意,当覆盖复制构造函数,即使你不使用该方法),保持概念上的“声音”和也是一种内部文件.如果你的类得到很多的使用,你可能会最终提供一个operator =,这样你可以保持自动生成的实例id与这个操作符下的类成员赋值的分离.等等

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...