只出现一次的数字-136
class Solution {
public:
int singleNumber(vector<int>& nums) {
//按位异或的规则是:两个二进制位相同时结果为0,不同时结果为1
//具有自反性,两个二进制位相同时结果为0,一个数(a)和0按位异或的结果为a。
int result = 0;
for(int i=0;i<nums.size();i++)
{
result ^= nums[i];
}
//循环按位异或后成对出现的数字会相互抵消,最后剩下的就是唯一的数组
return result;
}
};
每日问题
什么是 C++ 中的初始化列表?它的作用是什么?
C++中的初始化列表
在C++中,初始化列表是用于初始化类对象成员的一种特殊语法。它在类的构造函数定义中,通过:后面跟随成员变量的初始化表达式实现。
语法
class MyClass{
int a;
int b;
public:
MyClass(int x, int y) : a(x), b(y){
//构造函数体(可选)
}
};
这里的: a(x),b(y)就是初始化参数列表。它在构造函数体执行之前完成成员变量的初始化。
作用
初始化参数列表的主要作用是高效和正确地初始化类成员,尤其是以下几种情况:
1.初始化常量成员
常量(const)类成员必须在初始化时赋值,而不能在构造函数体内赋值:
class MyClass{
const int a;
public:
MyClass(int x):a(x){}
};
2.初始化引用成员
引用类型(&)成员必须在初始化列表中赋值,因为它们需要在定义时绑定:
class MyClass{
int& ref;
public:
MyClass(int& x):ref(x){}
};
3.调用基类构造函数
当派生类需要调用基类的构造函数初始化时,必须使用初始化参数列表:
class Base{
public:
Base(int x){}
};
class Derived : public Base{
public:
Derived(int y):Base(y){}
};
4.调用成员对象的构造函数
如果类包含类型为其他类的对象成员,这些对象成员通常需要通过构造函数初始化:
class Member{
public:
Member(int x){}
};
class MyClass{
Member m;
public:
MyClass(int y):m(y){}
};
5.提高效率
在初始化列表中赋值直接初始化变量,避免了在构造函数中现默认初始化再赋值的额外开销。
初始化列表与构造函数体的区别
class MyClass{
int a;
int b;
public:
MyClass(int x, int y){
a = x;
b = y;
}
MyClass(int x,int y):a(x),b(y){
//初始化列表直接初始化a 和 b
}
};
初始化列表直接初始化,效率更高。
构造函数体内赋值可能导致多次初始化(现默认初始化,再赋值),效率较低。
初始化列表和在构造函数体内赋值有什么区别?
1.初始化顺序
初始化列表:成员变量在构造函数体执行之前完成初始化,成员的初始化顺序是根据它们在类中的声明顺序,而不是在初始化列表中的书写顺序。
class MyClass{
int a;
int b;
public:
MyClass(int x,int y):b(y),a(x){}//实际初始化顺序是a然后b
};
构造函数体内赋值:成员变量会先默认初始化(调用其默认构造函数),然后在构造函数体中通过赋值语句重新赋值。
2.效率差异
初始化列表效率更高:初始化列表直接调用成员的构造函数完成初始化,无需经历额外的默认构造和赋值过程
MyClass(int x, int y) : a(x), b(y) {} // a 和 b 被直接初始化
构造函数体内赋值效率较低:成员变量会先进行默认初始化(如果类型是类对象,则会调用默认构造函数),然后再通过赋值语句修改其值。这会导致额外的开销。
MyClass(int x, int y) {
a = x; // 先默认构造,再赋值
b = y;
}
3.必须使用初始化列表的情况
某些情况下,构造函数体内赋值无法满足需求,必须使用初始化列表:
1.初始化常量成员:常量(const)类成员必须在初始化时赋值,不能通过赋值语句修改。
2.初始化引用成员:引用类型(&)成员必须在初始化列表中赋值,因为它们需要在定义时绑定,不能通过赋值语句完成。
3.成员对象没有默认构造函数:如果成员对象是某个类的实例,而该类没有默认构造函数,则必须通过初始化列表调用其其他构造函数。
4.构造顺序的隐含特定
初始化列表:初始化列表的顺序由成员变量在类中声明的顺序决定。
构造函数体内赋值:即使顺序写对了,仍会因为两步(默认构造+赋值)而显得繁琐。