OOP Lec9: Copy & Move

Copy and Move

拷贝构造

默认拷贝

void func(Currency p){
    cout << "x = " << p.dollars();
}
...
Currency bucks(100, 0);
func(bucks);

这个时候会发生隐式的拷贝和构造:Currency p(bucks);

这种特殊的构造,会调用拷贝构造函数

class HowMany{
public:
    HowMany(){}
    ~HowMany(){}
    HowMany(const HowMany&);// 这个
private:
}
HowMany::HowMany(const HowMany& x){}

什么时候需要自己重新写拷贝构造:成员变量中有指针、非内存的资源(文件句柄,socket 等)。默认的拷贝构造是 member-wise copy,依次调用其成员的拷贝构造函数,指针只拷贝指向的地址而不拷贝资源。

编译器的优化细节:函数要返回本地对象的时候,编译器通过某种方法将其地址安排在调用它的函数旁边(前面),在函数结束后母函数仍然能直接访问此对象,从而避免了拷贝构造。

自定义拷贝构造

假设我们有个 Person 类,使用 char* 存储人名,每次构造时动态分配空间。

显然,在拷贝构造时我们需要复制一份新的人名,避免旧对象销毁之后,新对象无法访问人名。

class Person{
public:
    Person(const char* s);
    ~Person();
    Person(const Person& rhs);
    void print();
    // other func...
private:
    char *name;
    Person& operator=(const Person& rhs); // forbidden "="
    // more info...
};
Person::Person(const char* s){
    name = new char[::strlen(s) + 1];
    ::strcpy(name, s);
}
Person::~Person(){
    delete[] name;
}
Person::Person(const Person& rhs){
    name = new char[::strlen(rhs.name) + 1];
    ::strcpy(name, rhs.name);
}

如果不需要拷贝构造,可以将其声明为 private,在外部调用时就会报错。这种情况下,不需要函数实现。

private:
    Person(const Person& rhs);

参数与返回类型

基本类型:

void f(Student  i);
void f(Student* p);
void f(Student& p);
Student  f();
Student* f();
Student& f();

可能有的问题:

char* foo(){
    char *p;
    p = new char[10];
    strcpy(p, "something");
    return p;
}
void bar(){
    char *p = foo();
    delete[] p;// if the function is more complicated, maybe need or not
}

在工程中,非常难判断是否需要删除内存。所以,除非语义上需要,不要让对象的 newdelete 分离,不要让一个函数申请一块内存再把它传递出去。

移动拷贝构造

语法

含义:参数为右值引用的拷贝构造。

原型:

DynamicArray::DynamicArray(const DynamicArray&& rhs);
vector<int> v1{1, 2, 3, 4};
vector<int> v2 = v1; // v2 是 v1 的副本
vector<int> v3 = std::move(v1); // 调用移动构造函数

统一初始化 Uniform Initialization

这是 C++11 标准启用的新特性。

对于简单的类或者容器内部的类,我们可以不写构造函数,而是用花括号进行统一初始化

如果类没有构造函数,参数应按照成员的声明顺序给出;如果有,参数应按照构造函数的参数顺序给出。

class Test{
    int a, b;
};
Test t{0, 0};
Test *pt = new Test{1, 2};
int *a = new int[3]{1, 2, 0};
vector<string> vec = { "first", "second", "third"};

查看更多:Brace initialization for classes, structs, and unions | Microsoft Learn

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇