operator
如下代码重载了&,使得address的类型为 int
struct AAA{
int operator & (){
return 10;
}
};
void testOperator(){
AAA a;
auto address=&a;
cout<<"address的类型:"<<typeid(address).name()<<endl;
}
但是operator在重载的时候有很多需要注意的地方
重载“=”
struct AAA {
~AAA() { delete m_value;}
AAA() : m_value(new int()) {}
AAA(const AAA& rhs) : m_value(new int(*(rhs.m_value))) {}
AAA& operator = (const AAA& rhs) {
*m_value = *(rhs.m_value);
return *this;
}
private:
int* m_value;
};
void testOperator(){
AAA a;
AAA b=a; //调用拷贝构造函数
b=a; //调用拷贝赋值函数
//cpp中默认的拷贝赋值函数是按值拷贝,也就是说,执行完这句,a和b指向同一个内存
//此时如果释放b的内存,则a和b所指的内存就都被释放掉了
//如果b释放过内存之后,a又一次对该块内存进行释放,就会出现问题
}
此时,我们需要重载“=”,防止浅拷贝
reinterpret_cast
void testReinter() {
int a = 1;
auto p = reinterpret_cast<char*>(&a); //将&a强转成char*的指针
//检测大小端的另一种方式
if(p[0] == 1) std::cout << "the system is little endian\n";
else std::cout << "the system is big endian\n";
// reinterpret_cast
// static_cast
// const_cast
// dynamic_cast
// c like cast——c类型的cast很强大,除了dynamic_cast之外,其余三种cast都是通过c like cast
//来进行转换的。比如下面的例子:
auto pp = (char*)(&a); //没有问题
const AAA bb;
auto pbb = const_cast<AAA*>(&bb); //正确
auto cbb = (AAA*)(&bb); //正确
int c = 100;
auto cc = static_cast<char>(c); //正确
auto ccc = (char)c;
//C++中设计出这么多的cast,是为了让使用者明确各个cast的用法。各种cast是不能相互转换的
}
sizeof
c++11之前
class Empty {};
class Base { int a; };
class Derived : Base { int b; };
class Bit { unsigned bit: 1; };
// c++11 before
void testSizeof() {
Empty e;
Derived d;
Base& b = d;
Bit bit;
std::cout << sizeof e << std::endl; // 1
std::cout << sizeof(Empty) << std::endl; // 1
std::cout << sizeof(&e) << std::endl; // 4(32位),8(64位)
std::cout << sizeof(Derived) << std::endl; // 8
//std::cout << sizeof(void) << std::endl; //会报错,因为void没有大小
//std::cout << sizeof(int[]) << std::endl; //会报错,对于非明确的类型会报错,因为数组大小未知
//std::cout << sizeof(bit.bit) << std::endl; //会报错,因为大小不足一个字节
}
2019.6.4补充
感谢大佬指出问题。
c++11之后(以后补)
static
1、static在外部文件中的语法
//globalA是在预编译的时候就已经分配好了内存地址空间了
//两个文件都定义了static全局变量的话,生成顺序是不确定的,因此最好不要这么用static
static int globalA = 0; //声明了文件范围内全局可见的globalA。
void printInfo() {
//函数内static变量。只有当函数第一次被调用时,才会给localStatic分配内存空间。
//第二次调用的时候就继续使用之前分配的内存空间
//这种static的使用方式也是不推荐的:
//比如:多线程的情况下容易出现bug.比如两个线程都调用了这个函数,两个线程可能两边打印出来的结果都是2
static int localStatic = 0;
++localStatic;
std::cout << S::s << " " << globalA << " " << localStatic << std::endl;
}
2、static在类中的语法
struct S {
static int s;
};
// sizeof(S) == 1 因为s只是归属于S,但是他是static,所以s不是S的成员。因此S的大小和空类是一样的,因此是1
int S::s = 10; //初始化
struct Foo;
struct SS {
static int a[];
static Foo foo;
static SS ss;
};
//实例化
int SS::a[10];
struct Foo {};
Foo SS::foo;
SS SS::ss;
static_assert(c++11)
static_assert能做的事情,assert也能做。但是assert有一定的问题
- 1、assert是一个宏,在debug版本和release版本是不一致的
- 2、assert在运行时期才会发现问题,而static_assert在编译时期就能发现问题,相当于缩短了开发的迭代周期
但是static_assert里面跑的东西只有在编译期才会发生作用,因此下面代码中发的判断语句要用assert
因为a==b是在运行期进行判断的,而不是编译期
void testStaticAssert() {
int a = 4;
int b = 5;
//static_assert能做的事情,assert也能做。但是assert有一定的问题
//1、assert是一个宏,在debug版本和release版本是不一致的
//2、assert在运行时期才会发现问题,而static_assert在编译时期就能发现问题,相当于缩短了开发的迭代周期
//但是static_assert里面跑的东西只有在编译期才会发生作用,因此下面的判断语句要用assert
//因为a==b是在运行期进行判断的,而不是编译期
assert((a == b) && "only work for int for 32 bit");
}
template<typename T>
void func(T t) {
//编译时期如果不满足编译条件,就会停止编译,并输出 only for alignof 4
static_assert(alignof(T) == 4, "only for alignof 4");
}