右值引用,移动拷贝构造,移动复制函数,柔性数组,友缘

编程入门 行业动态 更新时间:2024-10-26 06:28:14

右值引用,移动拷贝构造,移动复制函数,<a href=https://www.elefans.com/category/jswz/34/1753562.html style=柔性数组,友缘"/>

右值引用,移动拷贝构造,移动复制函数,柔性数组,友缘

文章目录

  • 一,右值引用
  • 二,移动拷贝构造函数,移动赋值函数
  • 柔性数组
  • 友缘
    • 特点
    • 友缘的实现方案
      • 1,函数友缘
      • 2,成员函数友缘
      • 3,类友缘

一,右值引用

将亡值:表达式的运行中产生的一个不具有名字的实体;
右值引用:对将亡值和纯右值进行引用

 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;
}

更多推荐

右值引用,移动拷贝构造,移动复制函数,柔性数组,友缘

本文发布于:2024-03-05 14:32:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1712553.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:柔性   数组   函数   友缘

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!