c源码unique_ptr(建站abc源码)
本文目录一览:
- 1、[c++专家答]C++作为C语言的超级语言 需要 restrict 关键字吗?
- 2、如何使用C++ 11标准中的unique_ptr操作二维数组
- 3、std::auto_ptr是什么?
- 4、c++为什么用右值引用
- 5、为什么c++ unique_ptr指针为右值时可以赋给share_ptr
[c++专家答]C++作为C语言的超级语言 需要 restrict 关键字吗?
现在的C++编译器,无论是GCC,Clang,VC++,IBM XL C++等,这些主流的C++编译器都提供了restrict关键字的支持,只是似乎书写的形式有所变化,如可能是__restrict__,__restrict等 ,而restrict是限制Pointer Alias的,这和unique_ptr完全是两码事,限制Pointer Alias有助于编译器做优化。至于为什么C++标准委员会不加,我现在也不知道,我也感觉很诧异,不过下次我会记得问导师Michael,但是可能要等到8月份了,我现在手上也有一大堆的C++问题等着问他,包括Module System是否在C++17挂掉了等,因为我上次看见有人在我的评论说这个挂了,我比较疑惑。
然后补充一下restrict的用法,我以GCC产生汇编指令的例子来补充一下,比较直观
void f(int *a, int *b, int *c)
{
*a += *c;
*b += *c;
}
-O3后的汇编代码
f(int*, int*, int*):
movl (%rdx), %eax
addl %eax, (%rdi)
movl (%rdx), %eax
addl %eax, (%rsi)
ret
加上restrict
void f(int * __restrict__ a, int* __restrict__ b, int* __restrict__ c)
{
*a += *c;
*b += *c;
}
-O3后
f(int*, int*, int*):
movl (%rdx), %eax
addl %eax, (%rdi)
addl %eax, (%rsi)
ret
可以很清楚的看见是4条指令变为了3条指令,而少掉的一条就是第二次的load c
然后看看unique_ptr
#include memory
using namespace std;
void f(std::unique_ptrint a, std::unique_ptrintb, std::unique_ptrint c)
{
*a += *c;
*b += *c;
}
-O3 -std=c++11
f(std::unique_ptrint, std::default_deleteint , std::unique_ptrint, std::default_deleteint , std::unique_ptrint, std::default_deleteint ):
movq (%rdx), %rdx
movq (%rdi), %rax
; *a += *c
movl (%rdx), %ecx
addl %ecx, (%rax)
movq (%rsi), %rax
; *b += *c
movl (%rdx), %edx
addl %edx, (%rax)
ret
所以,可见,unique_ptr和restrict完全是两码事。
如何使用C++ 11标准中的unique_ptr操作二维数组
#include memory
#include iostream
using namespace std;
templateclass T
struct array_deleter
{
void operator()(T* x) const { delete[] x; }
};
typedef unique_ptrdouble, array_deleterdouble unique_double_array;
typedef unique_ptrunique_double_array, array_deleterunique_double_array unique_double_matrix;
unique_double_matrix getMatrix(int row, int col)
{
unique_double_matrix r(new unique_double_array[row]);
for (int i = 0; i row; ++i)
r.get()[i].reset(new double[col]);
return std::move(r);
}
void proc(unique_double_matrix m, int row, int col)
{
for (int i = 0; i row; ++i)
for (int j = 0; j col; ++j)
m.get()[i].get()[j] += 1;
}
int main()
{
unique_double_matrix m(getMatrix(3, 3));
for (int i = 0; i 3; ++i)
for (int j = 0; j 3; ++j)
m.get()[i].get()[j] = 1 + i * 3 + j;
proc(m, 3, 3);
for (int i = 0; i 3; ++i)
{
for (int j = 0; j 3; ++j)
cout m.get()[i].get()[j] " ";
cout endl;
}
return 0;
}
这语法写得人蛋疼……
std::auto_ptr是什么?
std::auto_ptr是C++标准库里面的模版类,
属于智能指针。
也就是说,
设计理念就是分配了指针后,不需要担心释放的问题,
属于RAII
(Resource
Acquisition
Is
Initialization)范畴,目的是为了解决资源自动回收。
具体定义可参看源码,
它有get成员函数,只是返回对应存储的指针地址。
注意:
C++11标准已经用unique_ptr取代了auto_ptr。
c++为什么用右值引用
右值引用是C++11中最重要的新特性之一,它解决了C++中大量的历史遗留问题,使C++标准库的实现在多种场景下消除了不必要的额外开销(如std::vector, std::string),也使得另外一些标准库(如std::unique_ptr, std::function)成为可能。即使你并不直接使用右值引用,也可以通过标准库,间接从这一新特性中受益。为了更好的理解标准库结合右值引用带来的优化,我们有必要了解一下右值引用的重大意义。
右值引用的意义通常解释为两大作用:移动语义和完美转发。本文主要讨论移动语义。
移动语义
======
移动语义,简单来说解决的是各种情形下对象的资源所有权转移的问题。而在C++11之前,移动语义的缺失是C++饱受诟病的问题之一。
举个栗子。
问题一:如何将大象放入冰箱?
答案是众所周知的。首先你需要有一台特殊的冰箱,这台冰箱是为了装下大象而制造的。你打开冰箱门,将大象放入冰箱,然后关上冰箱门。
问题二:如何将大象从一台冰箱转移到另一台冰箱?
普通解答:打开冰箱门,取出大象,关上冰箱门,打开另一台冰箱门,放进大象,关上冰箱门。
2B解答:在第二个冰箱中启动量子复制系统,克隆一只完全相同的大象,然后启动高能激光将第一个冰箱内的大象气化消失。
等等,这个2B解答听起来很耳熟,这不就是C++中要移动一个对象时所做的事情吗?
“移动”,这是一个三岁小孩都明白的概念。将大象(资源)从一台冰箱(对象)移动到另一台冰箱,这个行为是如此自然,没有任何人会采用先复制大象,再销毁大象这样匪夷所思的方法。C++通过拷贝构造函数和拷贝赋值操作符为类设计了拷贝/复制的概念,但为了实现对资源的移动操作,调用者必须使用先复制、再析构的方式。否则,就需要自己实现移动资源的接口。
为了实现移动语义,首先需要解决的问题是,如何标识对象的资源是可以被移动的呢?这种机制必须以一种最低开销的方式实现,并且对所有的类都有效。C++的设计者们注意到,大多数情况下,右值所包含的对象都是可以安全的被移动的。
右值(相对应的还有左值)是从C语言设计时就有的概念,但因为其如此基础,也是一个最常被忽略的概念。不严格的来说,左值对应变量的存储位置,而右值对应变量的值本身。C++中右值可以被赋值给左值或者绑定到引用。类的右值是一个临时对象,如果没有被绑定到引用,在表达式结束时就会被废弃。于是我们可以在右值被废弃之前,移走它的资源进行废物利用,从而避免无意义的复制。被移走资源的右值在废弃时已经成为空壳,析构的开销也会降低。
右值中的数据可以被安全移走这一特性使得右值被用来表达移动语义。以同类型的右值构造对象时,需要以引用形式传入参数。右值引用顾名思义专门用来引用右值,左值引用和右值引用可以被分别重载,这样确保左值和右值分别调用到拷贝和移动的两种语义实现。对于左值,如果我们明确放弃对其资源的所有权,则可以通过std::move()来将其转为右值引用。std::move()实际上是static_castT()的简单封装。
为什么c++ unique_ptr指针为右值时可以赋给share_ptr
只是这个操作c源码unique_ptr的话c源码unique_ptr,不会。因为这个 unique_ptr 会立刻被赋值为 nullptr c源码unique_ptr,即不指向任何对象。右值一般接着就会被立即销毁c源码unique_ptr,所以没有问题
将来这个 shared_ptr 可能会赋值给别c源码unique_ptr的 shared_ptr ,这样是有可能造成两个 shared_ptr 指向一个对象。没有这个心理准备也不会把 unique_ptr 赋给 share_ptr