类和对象

类属性与类方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
using namespace std;

class A {
public :
    A(int x) {
        cout << "class A's constructor" << endl;
    }
};

class Point {
public :
    Point();
    Point(int x, int y);
    int x() const;
    int y() const;
    int x_cnt() const;
    void set_x(int x);
    void set_y(int y);
    static int output_cnt();
    ~Point();

private :
    static int point_cnt;
    int __x, __y;
    mutable int __x_cnt;
    A __a;
};

int Point::point_cnt = 0;

int Point::output_cnt() {
    return Point::point_cnt;
}

Point::Point() : __x_cnt(0), __a(2) {
    Point::point_cnt += 1;
}

Point::Point(int x, int y) :
    __x(x), __y(y),
    __x_cnt(0), __a(4) {
    Point::point_cnt += 1;
}

Point::~Point() {
    Point::point_cnt -= 1;
}

int Point::x() const {
    this->__x_cnt += 1;
    return this->__x;
}

int Point::y() const {
    return this->__y;
}

int Point::x_cnt() const {
    return this->__x_cnt;
}

void Point::set_x(int x) {
    this->__x = x;
}

void Point::set_y(int y) {
    this->__x = y;
}

void func() {
    Point c, d;
    cout << "func : " << Point::output_cnt() << endl;
    return ;
}

int main() {
    Point a(2, 3), b;
    const Point c(3, 4);
    cout << a.x() << " " << a.y() << endl;
    cout << c.x() << " " << c.y() << endl;
    cout << c.x() << " " << c.y() << endl;
    cout << a.x_cnt() << " " << b.x_cnt() << " " << c.x_cnt() << endl;
    cout << "befor func : " << Point::output_cnt() << endl;
    func();
    cout << "after func : " << Point::output_cnt() << endl;
    return 0;
}

mutalbe 的中文意思是“可变的,易变的”,跟 constant(既 C++中的 const)是反义词。在 C++中,mutable 也是为了突破 const 的限制而设置的。被 mutable 修饰的变量,将永远处于可变的状态,即使在一个 const 函数中。

当一个属性、方法被 static 修饰的时候,就叫做类属性、类方法,又叫做静态属性、静态方法 。

没有被 static 修饰的属性,就叫对象属性、对象方法,又叫实例属性、实例方法和非静态属性、非静态方法。

当一个属性被声明成类属性,那么所有的对象,都共享一个值,所有对象都可以修改这个值,一经修改前面的值将会被丢弃。

而对象属性,每个对象的对象属性的值都互不影响,修改一个对象的对象属性,另一个对象的对象属性不变。

深拷贝和浅拷贝

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <cstring>
using namespace std;

class A {
public :
    A() {
        this->arr = new int[100];
    }
    A(const A &obj) : x(obj.x), y(obj.y) {
        this->arr = new int[100];
        memcpy(this->arr, obj.arr, sizeof(int) * 100);
    }
    int *arr;
    int x, y;
};

int main() {
    A a;
    a.x = 3, a.y = 6;
    a.arr[0] = 123;
    A b = a;
    b.arr[0] = 456;
    cout << a.arr[0] << " " << b.arr[0] << endl;
    cout << b.x << " " << b.y << endl;
    b.x = 6;
    cout << a.x << " " << a.y << endl;
    cout << b.x << " " << b.y << endl;
    return 0;
}

浅拷贝只是增加了一个指针指向已存在的内存地址;

深拷贝是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存

返回值优化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
using namespace std;

class A {
public :
    A() {
        cout << "constructor" << endl;
    }
    A(const A &obj) {
        cout << "copy constructor" << endl;
    }
};

A func() {
    A temp;
    return temp;
}

int main() {
    A a(func());
    return 0;
}

返回优化 直接编译(g++)

返回不优化 g++ -fno-elide-constructors

不优化:

  • step1:开辟 a 对象数据区
  • step2:调用函数 func
  • step3:开辟对象 temp_a 数据区
  • step4:调用 temp_a 对象的构造函数
  • step5:使用 temp_a 调用临时匿名变量的拷贝构造函数
  • step6:销毁 temp_a 对象
  • step7:使用临时匿名变量调用 a 的拷贝构造函数
  • step8:销毁临时匿名变量
  • step9:销毁 a 对象

输出结果:

constructor
copy constructor
copy constructor

优化后

  • step1:开辟 a 对象数据区
  • step2:调用函数 func
  • step3:将 temp_a 设置为 a 对象的替身
  • step4:调用 temp_a 对象的构造函数
  • step5:销毁 a 对象

输出结果:

constructor

返回值优化是 C++的一项编译优化技术,即删除保持函数返回值的临时对象。这可能会省略两次复制构造函数,即使复制构造函数有副作用。典型地,当一个函数返回一个对象实例,一个临时对象将被创建并通过复制构造函数把目标对象复制给这个临时对象。C++标准允许省略这些复制构造函数,即使这导致程序的不同行为,即使编译器把两个对象视作同一个具有副作用。