DataStructureAndAlgorithmInC++学习笔记 (一)

举报
大威天龙:- 发表于 2023/02/21 09:42:19 2023/02/21
【摘要】 第一章的学习,重点是理解右值与move的概念
  1. 递归:1. base condition 2. make procress to base
int f (int x) {
    if (x == 0) {
        return 0;
    } else {
        return 2 * f(x - 1) + x * x;
    }
}
void PrintDig(int x) {
    if (x >= 10) {
        PrintDig(x / 10);
    }
    cout << x % 10;
}
  • base case & make process
  1. 声明类对象的构造函数调用不当时,编译器可能会当成函数声明:
IntCell i1(); // 可能会被当作范围IntCell类型的函数
IntCell i1;
IntCell i1{};  // 如果希望零参调用构造函数,要么不带括号,要么带花括号。
  1. range-for 遍历并且不需要下标时可以采用
int result = 0;
for (int idx : target) {
    result++;
}

// 或者通过左值引用来修改被遍历的元素
for (auto& elem : target) {
    elem++;
}
  1. 左值引用的用途

    1. 给复杂结构起别名,提高代码可读性
    2. range-for 循环中修改迭代元素
    3. 避免返回时大对象的复制
  2. 模板函数与构成类的基本元素

template <typename type>
const type& FindMax(const vector<type>& vec)
{
    int maxIndex = 0;
    for (int i = 0; i < vec.size(); i++>) {
        if (vec[i] > vec[maxIndex]) {
            maxIndex = i;
        }
    }
    return vec[maxIndex];
}
#ifndef INTCELL_H
#define INTCELL_H

class IntCell()
{
public:
    explicit IntCell(int val = 0) : storedValue(val);
    int read();
    void write(int val);
private:
    int storedValue;    
};

#endif

lvalue: 被命名的非临时变量
rvalue: 没有被命名的但又确实存储在某个地方的临时变量(赋值符右边的准备赋给左边的这个计算结果或者函数返回的临时变量就是rvalue)
右值的这个临时变量是在什么时候释放?
右值引用比左值引用多一个特征就是可以引用右值,其余一样。

std::move()可以把值变成右值来避免左值复制时的copy开销,主要使用场景是移动赋值与移动构造函数,需要注意的是左值在调用过std::move()后将无法继续使用,因为移动构造函数会将传入的右值置空。

带bigFive的intCell

class IntCell()
{
public:
    explicit IntCell(int val = 0)
    {
        sotredVal = new int{val};
    }
    ~IntCell()
    {
        delete storedVal;
    }
    IntCell(const IntCell& rhs)
    {
        storedVal = new int{*rhs.storedVal};  // 一定要清楚调用变量的类型
    }
    IntCell(IntCell&& rhs)
    {
        storedVal = rhs.storedVal;
        rhs.storedVal = nullptr;
    }
    IntCell& operator=(const IntCell& rhs)
    {
        if (this != rhs) {
        		IntCell tmpCell = rhs;
             std::swap(*this, tmpCell);
        }
        return *this;
    }
    IntCell& operator=(IntCell&& rhs)
    {
        std::swap(storedVal, rhs.storedVal);  // swap member-by-member
        return *this;
    }
    int Read() const  // 写每个函数时,花十秒想一下返回类型,入参,可读性,内部逻辑
    {
        return *storedVal;
    }
    void Write(int val)
    {
        if (*storedVal !=val) {
            *storedVal = val;
        }
    }
private:
    int *storedVal;
};
  1. 模板函数 模板类 函数对象
template <typename obj, typename cmp>
const obj& FindMax(const vector<obj> vec, cmp isLessThan)
{
    int maxIndex = 0;
    for (int i = 1; i < vec.size(); i++) {
        if (isLessThan(vec[maxIndex], vec[i])) {
            maxIndex = i;
        }
    }
    return vec[maxIndex];
}

class CaseIntensiveCompare
{
public:
    bool operator()(const string& lhs, const string& rhs) {
        return lhs.size() < rhs.size();
    }
};

int main()
{
    vector<string> vec = {"ma", "junsong"};
    cout << FindMax(vec, CaseIntensiveCompare{});
}

  1. 第一章 总结

右值 右值引用 右值拷贝 右值赋值等C++11新增的特性是为了解决临时对象在传参、返回、拷贝、赋值时造成的复制开销。

swap : member-by-member 与 three move, 后者是通过move和copy assignment来实现的,所有copy assignment如果试图通过swap来实现的话 只能是member-by-member. 否则就会出现循环调用。

range for 的前提是容器支持迭代器。

move & assignment移动赋值的声明与使用
Object& operator= (Object&&);
Object newObject = std::move(oldObject);
把swap理解得太片面导致了误区,不只是threeCopy和threeMove三次swap std::move(); 也可以member-by-member swap
原文如下:
Finally, the move assignment operator at lines 23–27 is implemented as a member-by-
member swap. Note that sometimes it is implemented as a single swap of objects in the
same manner as the copy assignment operator, but that only works if swap itself is imple-
mented as a member-by-member swap. If swap is implemented as three moves, then we
would have mutual nonterminating recursion.

构造一个新的对象时 不管是=还是() 都是调用的构造函数。赋值函数只对已有对象的赋值起作用

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。