【问题标题】:Which constructor is called in STL container given default instantiation?在给定默认实例化的情况下,在 STL 容器中调用哪个构造函数?
【发布时间】:2021-03-11 17:24:16
【问题描述】:

"STL Tutorial and Reference Guide, Second Edition",在示例 6.8 中,作者 David Musser 给出了以下示例来演示,“在创建初始值的 N 个副本时,向量构造函数调用元素类型的拷贝构造函数”:

#include <iostream>
#include <vector>
class U {
    public:
        unsigned long        id;
        unsigned long        generation;
        static unsigned long total_copies;
        /************************************************************************/
        U() :
            id{0},
            generation{0}
        {
        }
        U(unsigned long n) :
            id{n},
            generation{0} 
        {
        }
        U(const U& src) :
            id{src.id},
            generation{src.generation+1} 
        {
            ++total_copies;
        }
        
        // EQUALITY
        bool operator==(const U& src) { return id == src.id; }
        bool operator!=(const U& src) { return id != src.id; }
        
        // ASSIGMENT
        U& operator=(const U& src) 
        {
            id = src.id;
            generation = src.generation + 1;
            ++total_copies;
        }
};

bool operator==(const U& u1, const U& u2) 
{
    return u1.id == u2.id;
}
bool operator!=(const U& u1, const U& u2) 
{
    return u1.id != u2.id;
}

unsigned long U::total_copies {0};

using std::cout;
using std::endl;

int main()
{
    vector<U> vector1, vector2(3);
    for (int i=0; i!=3; ++i)
        cout << "vector2[" << i << "].generation: "
             << vector2[i].generation << endl;
             
    cout << "Total copies: " << U::total_copies << endl;
    
    return 0;
}

据他所说,vector&lt;U&gt; vector2(3),应该:

  1. 调用U默认CTOR
  2. 然后调用U Copy CTOR,使用#1 的结果来填充向量,3x。

因此,他将结果打印如下:

vector2[0].generation: 1                                                                                                                
vector2[1].generation: 1                                                                                                                
vector2[2].generation: 1                                                                                                                
Total copies: 3  

但是,当我运行代码时,它显示默认 CTOR 被称为 3x,因此 generation == 0 并且没有创建任何副本。我的结果:

vector2[0].generation: 0                                                                                                                
vector2[1].generation: 0                                                                                                                
vector2[2].generation: 0                                                                                                                
Total copies: 0 

我也尝试过这个方法,其中我传递了U 一个参数,并且确实每次都调用副本 CTOR。这个编译器依赖吗?为什么会存在差异?在容器中初始化用户定义的对象时,我们应该注意这一点吗?

【问题讨论】:

  • @chris - 这与我得到的一致。作者如何使用 #4 CTOR 调用副本 CTOR?
  • 我包含了#3,因为其中一个重载具有相同的调用者用法。您需要查看的不仅仅是#4。
  • @chris - 这本书肯定是过时的(2001 年),这意味着他的代码使用以下格式:explicit vector( size_type count, const T&amp; value = T(), const Allocator&amp; alloc = Allocator()); 我想这将首先调用默认 CTOR(const T&amp; value=T()),然后复制剩余的。但自 2011 年以来,对 CTOR 的相同调用每次都只是调用默认 CTOR。对吗?
  • 是的,没错。

标签: c++ stl


【解决方案1】:

@chris 将我指向std::vector CTOR 页面cppreference.com。看来这本书的结果与我的不同的原因是,这本书写于 2001 年,称为以下 CTOR(直到 2011):

explicit vector( size_type count, 
                 const T& value = T(),
                 const Allocator& alloc = Allocator());

因此,调用vector&lt;U&gt; vector2(3)会先调用默认的UCTOR,然后复制一个。根据文档,“用具有值的元素的计数副本构造容器。” 但是,从 2011 年开始,以下 CTOR 被称为:

explicit vector( size_type count );

根据那里的文档,“使用默认插入的计数 T 实例构造容器。不制作副本。”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 2017-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2010-10-03
    相关资源
    最近更新 更多