c++备忘3

1. new后的内存需要释放,经常被人遗忘。有人想到可以利用对象,因为对象生命周期结束后,析构函数将会被调用,可以释放它指向的内存。

而对象的生命周期是程序自动控制的,因此可以轻松防止内存泄漏。

 

2. 智能指针的析构函数总是释放其指向的堆内存,因此,如果不是动态创建的堆内存,将会发生内存释放错误。

 

3. 两个指针指向同一块内存,容易发生double free的问题,如何防止?

a 定义赋值运算符,进行深度拷贝

b 建立所有权的转移,例如auto_ptr , unique_ptr(更严谨)

c 创建智能更高的指针,引用计数,赋值时,计数+1,指针过期时,计数-1,仅当最后一个指针过期时才调用delete,这是shared_ptr的概念。

 

4. auto_ptr<string> p1(new string("auto"));

auto_ptr<string> p2;

p2=p1;

p2接管了p1,这是好事,因为避免double free,但是如果后面访问p1将出错。

如果使用unique_ptr将在编译时出错,如下

unique_ptr<string> p1(new string("auto"));

unique_ptr<string> p2;

p2=p1;

但是,编译器允许将一个临时对象赋给unique_ptr,如下

unique_ptr<string> p3=unique_ptr<string>(new string("unique"));

此外,move() 能将一个unique赋值给另一个,实现所有权转移。如下

unique_ptr<string> p1,p2;

p1=unique_ptr<string>(new string("unique"));

p2=p1;

 

5. unique_ptr<double[]> p1(new double(5));

auto_ptr和shared_ptr只能用new,而unique_ptr可以用new[]

 

6. 在unique_ptr为右值时,unique_ptr 可以赋值给shared_ptr

unique_ptr<string> pup(generateU());  ---ok

shared_ptr<string> s1(pup);                 ----fail, unique_ptr is lvalue

shared_ptr<string> s2(generateU());------ok,,   unique_ptr is rvalue

 

7. c++提供了sstream族,读取string对象中的格式化信息,或将格式化信息写入string对象中---内核格式化。

ostringstream outstr;

string s1("OO");

outstr<<"file format is"<<s1<<"t";

string out = outstr.str();//返回一个被初始化为缓冲区内容的字符串对象。

cout<<out.

 

 

string lit = "there is a test file bellow"

istringstream instr(lit);

string word;

while(instr>>word)

{

cout<<word<<endl;

}

 

8. c++11特性

a)  新类型: long long, unsigned long long, char16_t, char32_t

b) 初始化列表 int x{5};  short quar[3]{1,2,3};

c) 缩窄,初始化列表语法防止缩窄。

char c1=1.57e27-----allow, but undefined behavior

char c1{1.57e27}-----compile error

char c1{66}----allow

d)

auto 申明变量类型

e)

decltype变量类型声明为表达式

decltype(x*n) q; q为x*n的类型

f)

返回类型后置

auto f2(double, int)->double;

g)

nullptr

h)

作用域内枚举

enum class New1{aa, bb, cc};

enum struct New2{aa, bb, cc};

调用时,New1::aa, New2::aa

i)

禁止自动转换

class Pe

{

int mem1 = 0;--------类内成员初始化

Pe(int);

explicit Pe(double);

explicit operator double() const;

};

Pe a, b;

b=0.5;----------fail, 禁止单参数构造函数导致自动转换。

double x = b;----fail, 禁止自动转换。

double x = double(b);---ok

j)

Useless::Useless(const Useless &f):n(f.n)--------拷贝构造函数

{

f的成员赋值给当前对象的成员

}

Useless:Useless(Useless &&f):n(f.n) -----------转移构造函数

{

f的内容复制给当前对象,且f成员内容置空

}

Useless &Useless::operator=(const Useless &f)-----赋值函数

{

f成员赋值给当前对象,深拷贝

}

Useless &Useless::operator=(Useless &&f)---转移赋值函数

{

return *this;

}

 

k)

如果提供了移动构造函数,编译器不会自动创建默认的构造函数,复制构造函数和赋值函数,在此情况下,可以使用default关键字声明这些默认版本;

class A{

public:

A(A &&);

A()=default;

A(const A&) = default;

A & operator=(const A &)=default;

如果想禁止复制对象,可禁用复制构造函数和赋值运算符

class A

....

A(const A&)=delete;

A &operator=(const A&)=delete;

 

l)

一个构造函数中使用另一个构造函数---------委托构造函数。

例如派生类构造函数可以调用基类构造函数。

using Base::Base;

Derived(int a, int b):ma(a),Base(b){};

 

m)管理虚方法

virtual void f() const override;说明您需要覆盖一个虚函数,如果声明与基类方法不匹配,编译器将会报错。如果不使用该关键字,基类同名的方法将被隐藏。

virturl void f() const final;禁止派生类覆盖该方法

 

n)lambda函数表达式

auto mod3=[](int x){return x%3==0;};  ---------返回类型自动推断

int count = std::count_if(numbers.begin(), numbers.end(), mod3);

 仅当表达式完全由一条返回语句组成时才能自动推断返回类型,否则需要显示指定

auto mod3=[&para](int x)->int{para++; return x%3==0;};

 

o)包装器

double test(double){return double*2.0;}

function<double(double)> e1=test;

p)省略参数

template<typename T, typename...Args>

void show(T value, Args...args)

{

...

}

show(x*x,'!',7,mr);

q)thread_local将变量声明为静态存储,随线程过期而过期。

库支持由原子操作atomic operation库和线程支持库组成

r)pair可以存储两个类型不同值,tuple可以存储任意多个类型不同值

s)regex库为正则表达式库

t)允许共用体成员有构造函数和析构函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值