为了账号安全,请及时绑定邮箱和手机立即绑定

C++程序设计语言1-3部分:笔记

标签:
C++

虚函数:常见的做法是编译器将虚函数的名字转换成函数指针表中对应的索引值,这张表就是所谓的虚函数表(vtbl)每个含有虚函数的类都有自己的vtbl用于辨识虚函数;

return unique_ptr<Shape>  {new Circle{p,r}}
基于上述定义,编译器将选择移动构造函数(move constructor)来执行从函数中移出返回值的任务,这意味着r=x+y+z不需要再拷贝Vector,只是移动它就足够了.

Vector::Vector(Vector&& a)
:elem{a.elem},sz{a.sz}{
    a.elem = nullptr;
    a.sz = 0;
}

Vector::Vector(Vector&& a)
:elem{a.elem},sz{a.sz}{
    a.elem = nullptr;
    a.sz = 0;
}

Shape(Shape&&) = delete;
Shape& operator = (Sape&&) = delete;//抑制操作


移动构造函数不接受const实参,毕竟移动构造函数最终要删除掉它的实参中的值,移动赋值运算符(move assignment)的定义与之类似;
当右值引用被用作初始化器或者赋值操作的右侧运算对象时,程序将使用移动操作;
Vector x(10);
Vector y(10);
Vector z(10);
z = x;
y = std::move(x) ; //执行移动操作,C++标准库的move()负责返回实参的右值引用;
return z; //移动操作

z = x;//拷贝操作;

Vector x = v1; //这个是初始化,不是重载的=,
x = v1; //初始化后,用这个赋值,才是初始化;
重载的方法则是:先申请空间,拷贝旧元素.删除新元素,返回*this;
x = v1 //x.operator=(T v1) ; //得这样理解才能知道为何返回*this;

Vector::Vector(Vector&& a)
:elem{a.elem},
sz{a.sz}{
  a.elem = nullptr;
  a.sz = 0;
}


封装是编译期的概念,是针对类型而非对象的,在类的成员函数中可以访问同类型实例对象的私有成员变量.

**类的成员函数中可以访问同类型实例对象的私有成员变量.
当右值引用被用作初始化器或者赋值操作的右侧运算对象时,程序将使用移动操作.
移动后,源对象所进入的状态应该能允许运行析构函数,我们也应该允许为一个移动操作后的源对象赋值;

移动的用法:
std::vector<thread> my_threads;

thread t{heartbeat};
my_threads.push_back(move(t));

Sharp(const Sharp7) = delete; //没有拷贝构造函数;

Vector<list<int>> vli(40);

模板的一个特殊用途是函数对象,我们可以像调用函数一样使用函数对象.
//小于5?

template<typename T>
class Less_than{
    const T val;
public:
    Less-than(const T& v):val(v){}
    bool operator()(const T& x) const {return x < val;} //谓词
};
用法:
Less_than<int> lit{42}; //初始化一个类,类的值为42,然后重载()
这样调用lit(43);;就会用42与43比;返回布尔值;
由于是模板,则string;
Less_than<string> its{"backet"};
bool b1 = lti(n);

作为算法:template<typename C, typename P>
int count(const C& c, P pred){
    int cnt = 0;
    for(const auto& x:c)
        if(pred(x))
            ++cnt;
        return cnt;
}
}

一个谓词的返回值要么是true,或false;
使用:void f(const Vector<int>& vec,const list<string>& lst, int x, const string& s)
{
    cout << "number of values less than"<<x
        << count(vec,Less_than<int> {x}) << '\n';
}

[&](int a){return a < x;}
[&]是一个捕获列表,它指明所用的局部名字,如(X)将通过引用访问,如果我们希望只"捕获X",则[&x],取值[=x],[]什么都不捕获,则为空;

可变参数模板:
别名:

using El = typename C:value_type;
using int32 = int;

using 可以和template结合使用:

template<typename Value>
using String_map = Map<string,Value>;

string_map<int> m;   //m则为Map<string,int>

std::string s {"for"};
std::list<std::string> slong {"gooo","listx"};


-----------------------------------------------
struct Entry {
    string name;
    int number;
    //friend ostream& operator<<(ostream&, Entry&);
};

ostream& operator<<(ostream &os, Entry &pd) {
    os << pd.name << " " << pd.number ;
    return os;
}

map通常用平衡二叉树实现;

map<string,int> phone_book{"David Hum",12345};

map 有序性;空间占用,适合有序的
unordered_map 无序,适合查找;unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。

forward_list<T>单向链表
deque<T> 双端队列
multiset<T>可重集合
multimap<K,V>允许重复关键字的map
unordered_multimap<K,V>
unordered_set<T>
unorder_multiset<T>

容器适配器:queue<T>,statck<T>,deque<T>,priority_queue<T>.
定长数据array<T,N>,bitset<N>

要排序,则要重载operator<;
void f (vector<Entry>& vec, list<Entry>& lst)
{
    sort(vec.begin(),vec.end());
    unique_copy(vec.begin(),vec.end(),lst.begin());
}

template<typename C, typename V>
vector<typename C::iterator> find_all(C& c,Vv){
    typename必不可以,通知编译器C的iterator为某种类型,而非值;
}

return unique_ptr<x>{new X{i}} //创建一个X,然后立即把它赋给nuique_ptr.
--------------------------------
shared_ptr在很多方面都和unique_ptr相似,shared_ptr的对象使用拷贝操作而非移动操作.

标准库直接支持在单一地址空间内并发执行多个线程,C++提供了一个适合的内存模型和一套原子操作.
并发设施: thread,mutex,lock,packaged_task,future;

void f() //函数

struct F{
    void operator()();
};

F//函数对象; F调用运算符;

thread t1{f};//在独立的线程中执行
thread t2{F()};

t1.join();
t1.join();

join()保证我们在线程完成后才退出user().join()的意思是,等待线程结束.

---------------
互斥:
mutex m;
thread使用lock()操作来获取一个互斥对象;
unique_lock<mutex> lock{m};

using namespace std::chrono;
---------------------------------------------    
auto t0 = high_resolution_clock::now();
this_thread::sleep_for(milliseconds{ 1000 });
auto t1 = high_resolution_clock::now();
std::cout << "----------------------------" << std::endl;
std::cout << duration_cast<nanoseconds>(t1 - t0).count();
  //std::cout <<typeid(t0).name();
std::getchar();
----------------------------------------------
queue<Message> mquess;
condition_variable 由mutex头文件提供;通信用的条件变量
mutex mmutex;

std::unique_lock对象以独占所有权的方式(unique owership)管理mutex对象的上锁和解锁操作,即在unique_lock对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而unique_lock的生命周期结束之后,它所管理的锁对象会被解锁。unique_lock具有lock_guard的所有功能,而且更为灵活。虽然二者的对象都不能复制,但是unique_lock可以移动(movable),因此用unique_lock管理互斥对象,可以作为函数的返回值,也可以放到STL的容器中。

consumer()消费者:
while(true){
unique_lock<mutex> lck{mmutex};
while(mcond.wait(lck))//释放lck并等待
    auto m=mqueue.front();//
    mqueue.pop();
    lck.unlock();
       //..处理m...
    }
}

void producer(){
{
    while(true){
    Message m;
    unique_lock<mutex> lck{mmm}//保护队列上的操作
    mqueue.push(m);
    mcond.notify_one(); //通知,释放锁(在作用域结束)
}
标准库的高层次抽象:

<future>头文件:
future和promise用来从一个独立线程上创建出的任务返回结果;
package_task是帮助启动任务以及连接返回结果的机制;
async()以类似调用函数的方式启动一个任务;
future和promise的关键点是它们允许在两个任务间传输值,而无须显式使用锁.系统高效地实现了这种传输.当一个任务需要向另一个任务传输某个值时,它把值放入promise中;

 
---------------------
原文作者:小明乐
原文链接:https://blog.csdn.net/catwan/article/details/85937317



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消