C/C++编程:直接初始化

1059 篇文章 286 订阅

直接初始化

定义

  • 明确的构造函数实参的集合初始化对象

语法

在下列场合进行直接初始化:

使用非空大括号或圆括号初始化变量

T object ( arg );
T object ( arg1, arg2, ... );
T object { arg };
T ( other )
T ( arg1, arg2, ... )

用 static_cast 表达式初始化纯右值临时量 (C++17 前)纯右值的结果对象 (C++17 起)

static_cast< T >( other )

使用 new 关键字和非空大括号或圆括号初始化变量

new T(args, ...)

在构造函数中,使用初始值设定项列表初始化基类和非静态成员

Class::Class() : member(args, ...) { ... }	

lambda 表达式中捕获的变量的副本中

[arg](){ ... }

我们在来看一个例子:

class BaseClass{
public:
    BaseClass(int n) :m_int(n){} // m_int is direct initialized
private:
    int m_int;
};

class DerivedClass : public BaseClass{
public:
    // BaseClass and m_char are direct initialized
    DerivedClass(int n, char c) : BaseClass(n), m_char(c) {}
private:
    char m_char;
};
int main(){
    BaseClass bc1(5);
    DerivedClass dc1{ 1, 'c' };
    BaseClass* bc2 = new BaseClass(7);
    BaseClass bc3 = static_cast<BaseClass>(dc1);

    int a = 1;
    function<int()> func = [a](){  return a + 1; }; // a is direct initialized
    int n = func();
}

直接初始化 VS 拷贝初始化

Primer中的说法

  • 当作用于类类型对象时,初始化的复制形式和直接形式有所不同:
    • 直接初始化直接调用与实参匹配的构造函数
    • 拷贝初始化总是调用赋值构造函数
  • 复制初始化首先使用构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象
  • 通常直接初始化和复制初始化仅在低级别优化上存在差异,然而,对于不支持复制的类型,或者使用非explicit构造函数的时候,它们有本质的区别
#include <iostream>
#include <fstream>

using namespace std;

int main(){
    ifstream file1("filename");//ok:direct initialization
    ifstream file2 = "filename";//error:copy constructor is private”
}

通常的误解

从上面的说法中,我们可以知道:直接初始化不一定要调用复制构造函数,而复制初始化一定要调用复制构造函数

然而,大多数人却认为,直接初始化是构造对象时要调用复制构造函数,而复制初始化是构造对象时要调用赋值操作函数,这其实是一大误解,因为只有对象被创建时才出现初始化,而赋值操作并不应用于对象的创建过程。至于为什么会出现这个误解,可能是因为复制初始化的写法中存在等号(=)吧。

我们来看个例子

string  str1 = "first";    //拷贝初始化,编译器允许把这句话改写为string str(“first”),但是string类必须有public的拷贝(移动)构造函数
string  str2(10,'a');     //直接初始化
string  str3(str2);      //直接初始化
string  str4 = string(10,'b');  //拷贝初始化
string  str5 = str4;        //拷贝初始化
string  str6 ("strr");       //直接初始化

如果误解调用拷贝构造函数的就是拷贝初始化,所以可能觉得str3也是拷贝初始化,这样就错了~

直接初始化:

  • 使用普通的函数匹配就可以完成的初始化叫做直接初始化,
  • 也就是说只是直接调用类的构造函数或者拷贝构造函数就能完成初始化的就是直接初始化。
  • 而str2和str3分别调用构造函数和拷贝构造函数,因此它们是直接初始化

拷贝初始化:

  • 将对象拷贝到正在创建的对象中,如果需要还要进行类型转换。
  • 这里也就是间接调用拷贝构造函数,当然大部分情况调用拷贝构造函数,有时也可能调用移动构造函数。

根据上面的例子,我们可能觉得,只有等号"="出现时,才会是拷贝初始化。

其实不然,在下面三个情况下也会发生拷贝初始化。

  • 将一个对象作为实参传递给一个非引用类型的实参(引用作为参数的话就可以省略拷贝这一操作,所以有时候可以这样来优化代码)
  • 从一个返回类型为非引用的函数返回一个对象
  • 花括号初始化一个数组的元素或一个聚合类(struct)的成员

参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值