构造函数之显式初始化与赋值

  大部分程序员写构造函数时是这样的:

class ClassA
{
    ClassA();
    ......
};

ClassA::ClassA()
{
    A=1;
    B=2;
    ......
}

  这一类构造函数包括了初始化和赋值两个步骤,在执行构造函数函数体内语句前,已经隐式调用了默认构造函数对变量进行初始化,函数体内语句其实是进行了一次赋值。
  更规范的是使用初始化列表进行初始化,即显式初始化。

ClassA::ClassA():A(1),B(2) 
{ 

}

  使用默认构造函数时,初始化成员的规则与初始化变量规则相同,即具有类类型的成员使用默认各自的默认构造函数来初始化,内置和复合类型的全局变量初始化为0,内置和复合类型的局部作用域的变量则不初始化。
  故而使用显示初始化是有好处的。第一是效率问题,因为要额外赋值一次,在函数体内赋值效率相对较低,当然如果你不在乎这一点点效率,我们还有第二条;第二条如果没有在函数体内给类成员提供初始化式,编译器会使用成员类型的默认构造函数;如果那个类没有默认构造函数,则初始化失败。另外const或引用类型的成员,无法赋值,只能在初始化列表中初始化。譬如:

class ClassA
{
private:
    int i;
    const int j;
    int &k;
public:
    ClassA(int B);
    ......
};

ClassA::ClassA(int B)
{
    i=B;    //ok
    j=B;    //error,不能给const对象赋值
    k=i;    //error,k没有初始化绑定一个对象
    ......
}

  正确初始化方式为

ClassA::ClassA(int B):i(B),j(B),k(i)
{

}

  以上参考自《c++primer》

### 构造函数中的初始化赋值 #### C++C++中,构造函数可以采用两种方设置对象的数据成员:初始化列表构造函数体内的赋值操作。 当使用初始化列表时,在创建对象的同时就完成了数据成员的初始化工作。这种方适用于常量成员、引用类型的成员以及一些自定义类型[^2]: ```cpp class MyClass { public: int value; // 使用初始化列表 MyClass(int v) : value(v) {} }; ``` 而在构造函数内部进行赋值,则是在默认构造之后再修改成员变量的内容。这通常用于简单的基本类型或指针指向的对象分配内存等情况: ```cpp class AnotherClass { public: std::string* strPtr; AnotherClass() { this->strPtr = new std::string("hello"); } }; ``` 需要注意的是,对于某些特殊情况下(比如含有`const`修饰符或者引用),只能通过初始化列表完成其设定;而对于其他情况两者都可以达到相同的效果,但从效率上讲推荐优先考虑初始化列表的方因为这样可以直接构造而不是先调用一次无参构造然后再赋新。 #### Java Java 中同样存在这两种机制来进行字段的初始化处理。不过由于语法特性不同,具体表现形有所变化。 对于静态域(static field),无论哪种方法都将在类加载阶段被赋予初始。但对于实例域(instance field), 如果是在声明处直接给定初的话, 那么这些语句会在任何的构造器执行之前被执行。而如果是在构造器内利用 `this.fieldName = ...` 的方进行赋值则会覆盖之前的默认[^1]: ```java class Example { final String name; // 必须要初始化 public Example(String n){ this.name = n; // 初始化final成员需在此处完成 } } ``` 另外一点得注意的地方在于父类构造器的调用。子类可以通过 `super()` 来指定想要调用哪个版本的父亲级别的构造器,并且这条指令必须放在第一个位置。如果不加说明,默认会尝试调用无参数版的超类构造器。 #### Python Python 对象创建过程中也涉及到类似的逻辑差异。然而它并没有严格意义上的“初始化列表”,所有的准备工作都是在一个名为 `__init__` 的特别方法里完成的。这里既可以做真正的初始化也可以只是简单的赋值动作[^4]。 ```python class Sample: def __init__(self, val=None): self.value = [] if not isinstance(val, list) else val[:] # 这是一个初始化的例子 sample_instance = Sample([1, 2]) print(sample_instance.value) another_sample = Sample() print(another_sample.value) ``` 在这个例子中,`value` 属性要么接收传入列表的一个副本作为自己的状态,要么就被设为空数组。这种做法既包含了初始化的概念——即决定该属性应该持有怎样的结构,同时也涉及到了具体的数填充过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值