class and struct
目录
- 前文
- 问题
-
对象与引用
- 引用的传递
-
对象 copy
- shallow copy
-
depthcopy
- memcpy(data,a.data,sizeof(T) *n);
- 简单类型
- 复杂类型
- 指针类型的拷贝
- 原位构造
-
返回值优化 (RVO)
- 拷贝构造的现象
-
关键字
- default
- delete
-
函数重载
- 问题
- code
前文
c++ 中的class 和struct
struct 默认为 public
class 默认为private
问题
左值引用,右值引用区别?
什么时候需要定值浅拷贝和深拷贝的函数。
传值和传值的区别
对象与引用
引用的传递
返回引用就意味着是data[ind]的別名。
using namespace std;
class Vector{
public:
Vector(int n =100) : n(n),data(new int[n]){}
int &at(int ind){return data[ind];}
private :
int n ;
int *data;
};
int main(){
Vector arr;
for(int i=0; i
对象 copy
实际上两种copy是逻辑上的
class Vector{
public:
Vector(int n =100) : n(n),data(new int[n]){}
int &at(int ind){
cout
shallow copy
int main(){
Vector arr;
for(int i=0; i
本代码将arr 拷贝给了arr2 ,本身属于两个不同的对象。
既然属于不同的对象,arr2的变动不应对arr1发生改变,但是事与愿违 ,因为受拷贝行为的影响,依次性的拷贝,由于是指针域,拷贝了同一个存储区的值。所以 arr2 发生更改,arr1 也会发生更改。
☕如果copy 的对象是指针类型时,这个方式就无法适用了.
depthcopy
指针类型并非是赋值关系,存arr2 应该是一个额外的存储区。
memcpy(data,a.data,sizeof(T) *n);
当前方法在一定的简单类型的场景下可以进行深拷贝,如果类型中存在了指针类型则也会出现两个指针指向同一个地址的的情况。
#include
#include
#include
#include
using namespace std;
#define BEGINS(x) namespace x {//begin of namespace
#define ENDS(x)} //end of namespace x
BEGINS(xxx)
class A {
public :
int x , y;
};
ostream &operator
class Vector{
public:
Vector(int n =100) : n(n),data(new T[n]){}
Vector (const Vector &a): n(a.n){
// 实现深拷贝
data = new T[n];
/*
for(int i = 0; i
简单类型
BEGINS(test1)
using namespace xxx;
int main(){
Vector arr;
for(int i=0; i arr2(arr);
arr2.output(10);
arr2[3]=1000;
arr.output(10);
arr2.output(10);
return 0;
}
ENDS(test1)
Arr size 8 0x7ffc86e546d0
0 1 2 3 4 5 6 7 8 9
Arr size 8 0x7ffc86e546c0
0 1 2 3 4 5 6 7 8 9
Arr size 8 0x7ffc86e546d0
0 1 2 3 4 5 6 7 8 9
Arr size 8 0x7ffc86e546c0
0 1 2 1000 4 5 6 7 8 9
☕由结果可以看到,很显然在copy后并没有影响arr1的指针域
复杂类型
BEGINS(test2)
using namespace xxx;
int main(){
Vector arr1;
for(int i = 0; i arr2(arr1);
arr2[3] = (A){4, 100};
arr2.output(10);
arr1.output(10);
return 0;
}
ENDS(test2)
Arr size 8 0x7ffc053fdeb0 //原
(0 , 0) (1 , 2) (2 , 4) (3 , 6) (4 , 8) (5 , 10) (6 , 12) (7 , 14) (8 , 16) (9 , 18)
Arr size 8 0x7ffc053fdea0
(0 , 0) (1 , 2) (2 , 4) (4 , 100) (4 , 8) (5 , 10) (6 , 12) (7 , 14) (8 , 16) (9 , 18)
Arr size 8 0x7ffc053fdeb0
(0 , 0) (1 , 2) (2 , 4) (3 , 6) (4 , 8) (5 , 10) (6 , 12) (7 , 14) (8 , 16) (9 , 18)
☕在不涉及对象中的(指针类型)(其中类型不需要深拷贝的场景)的情况下,可以实现深拷贝。
指针类型的拷贝
memcpy 是无法做到深拷贝的,无法完美的迁移。
BEGINS(test3)
using namespace xxx;
int main(){
Vector> arr1;
Vector> arr2(arr1);
arr2[2][2]=1000;
for(int i =0; i
原位构造
位构造 new (地址),其意思为:在某个地址上调用某个构造函数,构造一个相关的对象
如果数据类型T执行深拷贝的函数,将call T类型的拷贝构造函数
https://hedzr.com/c++/variant/in-place-construction-in-cxx/ 参考文章
Vector(const Vector &a):n(a.n){
// data = new T[n];//实现深拷贝, 带new 就调用n次构造函数
data =(T *)malloc(sizeof(T) * n);
/* for(int i = 0; i
返回值优化 (RVO)
对象: 已经经历了构造过程的数据区 。obj (申请对象数据区)→匹配构造函数 →完成构造(某对象)
-fno-elide-constructors 关闭返回值优化
拷贝构造的现象
按照流程应该是发生了三次构造 ? 为什么输出的解构为什么是同一个地址
按照正常逻辑, 中间的匿名对象应该没意义的 只是一个中转的功能
所以 第一步就吧匿名的临时变量优化掉
第二 ->tmep 拷贝给A对象 ,既然是拷贝他们是一模一样,加在temp对象所有的操作都会在去往A上
temp 对象其实可以看做A对象的别名,这就是返回值优化的最终版本
最终是 吧temp 当做A对象的引用了
#include
#include
#include
#include
#include
#include
关键字
隐形的行为,显性化 ,将代码的层面的规则,变成显示的规则
default
不一样点 :如果想要实现拷贝构造必须是初始化列表挨个拷贝, default 关键字会挨个执行拷贝方法
如果是默认的构造函数,他是一个东西
class A{
A() = default; // 隐性的行为显性化
A(const A &) =default;
A(const A &) {} //这和上面不是一个东西
};
delete
删除后,如果想使用,编译会直接报错。
class A{ |~
A() = default; // 隐性的行为显性化 |~
//A(const A &) =default; |~
A(const A &) = delete; |~
|~
// A() {} 这和上面不是一个东西 |~
}; |~
函数重载
如果一个作用内,函数名称相同,但是参数列表不同,称函数重载 (参数类型不同,参数个数不同(记得默认参数的问题))。
强调一下 和返回值没关系
问题
函数重载 好处?
- 有了函数重载,可以吧把一类通过参数区分的功能,命名成一个函数名。(精细化的处理流程)
- 通过函数参数的列表对函数进行提示
- 对函数进行扩展
code
int func(int x ){
return 2 * x;
}
double func(double x){
return 2.0 * x;
}
int ABS(int x ){
return abs(x);
}
double ABS(double x){
return fabs(x);
}
int main(){
cout
服务器租用托管,机房租用托管,主机租用托管,https://www.e1idc.com