一,右值引用
将亡值:表达式的运行中产生的一个不具有名字的实体;
右值引用:对将亡值和纯右值进行引用
int a = 10;
int& b = a;
int&& c = 10;
int&& d = c;//err此时c有了名字不再是右值
String &&fun()
{
String s2("yhping");
return s2;//s2有名字
}
二,移动拷贝构造函数,移动赋值函数
class String
{
char* str;
//特殊的构造函数,为了避免和下面的构造函数冲突,多加一个参数
String(char* p, int)
{
str = p;
}
public:
String(const char* p = NULL) :str(NULL)
//这样处理使得我们创建的对象的str不会为空
{
if (p != NULL)
{
str = new char[strlen(p) + 1];
strcpy(str, p);
}
else
{
str = new char[1];
*str = '\0';
}
cout << "Create String: " << this << endl;
}
~String()
{
if (str != NULL)
{
delete[] str;
}
str = NULL;
cout << "Destroy ~String(): " << this << endl;
}
//ostream& operator<<(const String*const this,ostream& outostream& out);
ostream& operator<<(ostream& out)const
{
if (str != NULL)
{
out << str;
}
return out;
}
//s1<<cout;
//s1.operator<<(cout);
//operator<<(&s1,cout);
/*String(const String& s)浅拷贝
{
str = s.str;
}*/
String(const String& s)
{
str = new char[strlen(s.str + 1)];
strcpy(str, s.str);
}
String& operator=(const String& s)
{
if (this != &s)
{
delete[]str;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
return *this;
}
String operator+(const String& s)const
{
/*char* p = new char[strlen(str) + strlen(s.str) + 1];
strcpy(p, this->str);
strcat(p, s.str);
return String(p);这样会造成内存的泄露没有对p进行释放空间*/
char* p = new char[strlen(str) + strlen(s.str) + 1];
strcpy(p, this->str);
strcat(p, s.str);
return String(p, 1);
}
String operator+(const char* s)const
{
char* p = new char[strlen(str) + strlen(s) + 1];
strcpy(p, this->str);
strcat(p, s);
return String(p, 1);
}
String(String&& s)//右值引用的移动拷贝构造函数
{
cout << "move copy conststruct :" << this << endl;
str = s.str;
s.str = NULL;
}
String& operator=(String&& s)//移动赋值函数
{
if (this != &s)
{
// delet[]str;//此代码避免s1之前指向的空间没有释放,导致内存泄漏;
//str = s.str;
//s.str = NULL;
s.str = Relese(s.str);
}
cout << this << "move operator=: " << &s << endl;
return *this;
}
char* Relese(char* p)
{
char* old = str;
str = p;
return old;
}
};
ostream& operator<<(ostream& out, const String& s)
{
s << out;
return out;
}
String operator+(const char* c, const String& s)
{
/*char* p = new char[strlen(s.str) + strlen(c) + 1];
strcpy(p, c);
strcat(p, s.str);
return String(p, 1);*/
return s + String(c);
}
String fun()
{
String s2("yhping");
return s2;
}//需要创建一个无名的对象(临时变量)有移动构造用移动构造,无则用普通的拷贝构造
//这里的s2虽为有名但是这是系统给创建将亡值对象的特殊函数(移动拷贝构造);
int main()
{
String s1;
s1 = fun();
cout << s1 << endl;
return 0;
}
int main()
{
String s1= fun();//系统优化的结果
cout << s1 << endl;
return 0;
}
柔性数组
class String
{
private:
struct StrNode//这种结构的结构体,柔性数组结构,
//c语言中可以使结构体产生柔性数组,结构体最后一个元素大小可以是未知的数组
{
int ref;
int len;
int size;
char data[];
};
StrNode* pstr;
public:
String(const char* p = NULL) :pstr(NULL)
{
int len = strlen(p);
pstr = (StrNode*)malloc(sizeof(StrNode) + len * 2 + 1);
pstr->ref = 1;
pstr->len = len;
pstr->size = len * 2;
strcpy(pstr->data, p);
}
String(const String& s) :pstr(NULL)
{
if (this != NULL)
{
pstr = s.pstr;
pstr->ref += 1;
}
}
};
int mian()
{
String s1("yhping");
//String s2("hello");
String s2(s1);
String s3(s1);
String s4(s2);
return 0;
}
class Object
{
public:
int num;
struct Node
{
int data;
Node* next;
};
};
int fun()
{
Object obj;
Object::Node x;
}
class String
{
private:
struct StrNode//这种结构的结构体,柔性数组结构,
//c语言中可以使结构体产生柔性数组,结构体最后一个元素大小可以是未知的数组
{
int ref;
int len;
int size;
char data[];
};
StrNode* pstr;
public:
String(const char* p = NULL) :pstr(NULL)
{
int len = strlen(p);
pstr = (StrNode*)malloc(sizeof(StrNode) + len * 2 + 1);
pstr->ref = 1;
pstr->len = len;
pstr->size = len * 2;
strcpy(pstr->data, p);
}
String(const String& s) :pstr(NULL)
{
if (this != NULL)
{
pstr = s.pstr;
pstr->ref += 1;
}
}
~String()
{
if (pstr != NULL&&--pstr->ref==0)
{
free(pstr);
}
pstr = NULL;
}
String& operator=(const String& s)
{}
ostream& operator<<(ostream& out)const
{
}
char& operator[](const int index)//下标的重载
{
}
const char& operator[](const int index) const
{
}
};
int main()
{
String s1("yhping");
char x = s1[2];
s1[2] = 'x';
return 0;
}
友缘
破坏了对象的封装性
C++规定有四个运算符 =, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数)
特点
1,友缘不具备自反性
A是B的友缘,B不一定是A的友缘;
2,友缘不具有传递性
A和B是友缘,B和C是友缘,但是A和C没有关系;
3,友缘不具有继承性
友缘的实现方案
1,函数友缘
class Object
{
private:
int value;
public:
Object(int x) :value(x) {}
//将该函数注册为此类的友缘,所以该函数可以访问该类对象的私有,公有,和保护
friend ostream& operator<<(ostream& out, const Object& obj);
friend int main();
};
ostream& operator<<(ostream& out, const Object& obj)
{
out << obj.value;
return out;
}
int main()
{
Object obj(10);
cout << obj << endl;
cout << obj.value<<endl;
return 0;
}
2,成员函数友缘
//当用到友元成员函数时,需注意友元声明与友元定义之间的互相依赖。
//这是类Object的声明
class Object;
class Base
{
private:
int sum;
public:
Base(int x = 0) :sum(x) {}
//该函数是类Object的友元函数,因此可以通过该类的该函数破坏Object的封装性
void fun(Object& obj);
};
class Object
{
private:
int value;
public:
Object(int x) :value(x) {}
friend void Base::fun(Object& obj);
};
//只有在定义类Object后才能定义该函数,毕竟,它被设为友元是为了访问类A的成员
//如果在Object之前就定义会报错
void Base::fun(Object& obj)
{
obj.value = obj.value + sum;
cout <<"Object value: "<< obj.value << endl;
}
int main()
{
Object obja(20);
Base base(10);
base.fun(obja);
return 0;
}
3,类友缘
让Object的成员函数能够访问Base这个对象的公有私有,保护成员
例如将类 B 声明为类 A 的友元类,那么类 B 中的所有成员函数都是类 A 的友元函数,可以访问类 A 的所有成员,包括 public、protected、private 属性的。注意要访问其A的成员,必须在A类定义之后在定义相应的函数;
class Base;
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x) {}
void fun(Base& x);
void Show(const Base& x);
};
class Base
{
friend class Object;
private:
int num;
public:
Base(int x = 0) :num(x) {}
};
void Object::fun(Base& x)
{
x.num += 10;
}
void Object::Show(const Base& x)
{
cout << x.num << endl;
}
c11引入的新标准
int main()
{
int ar[] = { 12,23,34,45,56,67,78,89 };
for (auto x : ar)//for(ayto &x:ar)不是引用就将12,给x在打印,引用就是起了个别名
{
cout << x << endl;
}
return 0;
}