为什么空向量调用值类型的默认构造函数?

tor*_*ike 29 c++ stl vector stdvector

使用g ++,我观察到创建一个大小为零的向量会调用向量的参数化对象类型的构造函数一次.然后它被删除.为什么会这样?

#include <iostream>
#include <vector>
using namespace std;

class s
{
    public:
    s() { cout << endl << "default s constructor" << endl; }
    ~s() { cout << endl << "default s destructor" << endl; }

};

int main()
{
    vector<s> v(0);
}
Run Code Online (Sandbox Code Playgroud)

输出:

默认的构造函数

默认的析构函数

Ton*_*roy 29

因为您显式传递了一个初始大小,它调用的构造函数具有另一个默认值为的参数s().只是遗漏(0)(即std::vector<s> v;),它不会发生.

为了完整起见,标准23.2.4-2将您调用的构造函数定义为:

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

旁白(与C++ 03相关但不与C++ 11相关)

这个构造函数的另一个有趣的行为方面也定期提出SO:当请求的元素的初始数量> 0时,它将这些元素从原型参数复制构造到构造函数:

  • 人们经常会使用一个默认的构造函数来保留成员变量的未初始化,希望vector(n)几乎和底层的免费商店分配一样快,但是
  • 复制构造函数仍被调用n次,以将原型对象的"垃圾"内容复制到每个请求的元素中

这具有明显的性能成本,但是如果垃圾内容包括例如复制构造器只能假设有效的指针,则也可能使应用程序崩溃.类似地,即使是push_back这样一个未初始化的垃圾对象也是非常危险的- 它缺乏适当的值语义封装,并且可能在向量调整大小时被复制,算法操作就像std::sort()在向量上执行等.

  • 为了澄清,这个构造函数的签名是`vector(size_type size,const T&value = T(),const Allocator&= Allocator());`,这意味着调用你所做的,实际上是调用`vector(0,s( ),Allocator())`,从而创建一个临时的s对象. (3认同)
  • *只是*省略`0`会将对象定义变成函数声明:)也必须删除括号. (2认同)

Ken*_*nde 10

您正在调用的实际构造函数是(来自cplusplus.com):

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );
Run Code Online (Sandbox Code Playgroud)

因此,即使您只指定了大小,T也会为第二个参数创建一个新对象,因此也会在构造函数结束时销毁它.