恰好一年半这段时间没更新,其实不是啥好事,但另一方面又庆幸能来写一写。

 

概念都搞的比较模糊。持续杂记、整理下。

这记录的是当前(2024-11-21)的理解,有错的话持续修正。

 

三一法则五一法则

默认构造、拷贝构造、拷贝赋值、移动构造、移动赋值。这五个是编译器会默认合成的,且说他们的是否会合成规则就挺绕的了。它们一起构成了对象生命周期和内部数据的一些管理。涉及它们的有些是约定、有些是规定。

 

另管理资源的还有析构函数。

析构函数多半是要加virtual的,移动函数多半是要加noexcept的 。

 

左值、右值、右值引用。

右值引用也只是引用。

一个名字,它被定义为右值引用,引用到了某个对象,那这个名字的修改就会体现在这个变量上。

而右值引用,其实就是默认只能绑定到右值上的引用。

 

std::move

就是个强制类型转换。作用于一个非右值的实参后,让一个右值引用可以绑定到一个非右值上。

 

移动函数的书写约定

默认合成的是什么样的,和显式手写的有什么区别,和default修饰的,这三者之间关系。 default的和默认合成的,在实现本身上完全一致,但为什么default有啥用,

可以改变函数可访问性;

对复制的相关函数参数是否是const的改变;(移动的两个函数本身就必须是非const的形参)

增加可读性;

 

自定义的移动构造函数,当然你可以任意的写。但它存在的目的是能在某些重载被匹配时,使用起来更高效。如何高效,对于一些资源,在使用方已知并遵守规则情况下,对资源做“窃取”,为啥这样做,还是为了高效,因为使用方知道这个对象可以被窃取,所以让使用方有的选,可以选择走移动这条道,省掉不必要的复制代价。

 

复制控制的几个函数存在就是为了对一些特殊资源的管理。

如果都是普通资源,那直接各层级都走默认的就是合理且高效的。

而对于一些特殊资源,典型的例子就比如一块内存。

复制控制,合理适当的被使用场景是 当要深拷贝的地方,而移动发生在构造实参后面不在被使用的场景,(通常右值做为实参后不会再被使用,显示的std::move后的变量应该也被约定为不再被使用。)

对于移动,有了这些约定和使用规范后(需要使用者自己遵守),就可以再 移动构造函数或移动赋值操作符中,进行“窃取”之事了。仍以一块内存为例,那就是直接将实参的指针值赋值给当前被构造对象的对应属性,而不是new个新的再做深拷贝复制。

 

何时被调用

有了这些高效的 移动构造函数或移动赋值操作符 后,什么时候被调用呢,理论上当然是被优先调用为好了(当条件满足,能被匹配的前提下),这个应该就看重载匹配相关的知识点了。

除了这些收规矩的自动优化调用,显式约定调用的就是 强制类型转换,比如std::move来修饰下实参的情况下了。其实,还是走的重载匹配的路子,只是让这个实参做了 更深的修饰,让它符合被右值版本重载匹配的条件。

 

 

一些测试代码

通过类类型的属性,在起构造时,被调用的构造函数类型来观察:

 

#include <iostream>
 
 
class Nest {
public:
	Nest() {
		std::cout << "run in Nest()" << std::endl;
	}
 
	Nest(const Nest& robj) {
 
		std::cout << "run in Nest(const Nest &)" << std::endl;
	}
 
	Nest(Nest&& robj) /*noexcept*/ {
		std::cout << "run in Nest(const Nest &&)" << std::endl;
	}
};
 
class X {
public:
// 	X() :pt(new char[3]) {
// 		std::cout << "run in X()" << std::endl;
// 	}
	X(int ,int){}
 
	//X(const X& robj) = default;
	//X(X && robj) = default;
 
// 	X(X&& robj) /*noexcept*/ :pt(robj.pt) {
// 		robj.pt = nullptr;
// 		std::cout << "run in X(const X &&), curr robj.pt:" << (int)robj.pt << std::endl;
// 	}
 
	X& operator=(const X&) = default;
 
private:
	char* pt;
	Nest m_n;
};
 
void funTestObj(X& robj) {
	std::cout << "run in funTestObj(X& robj)" << std::endl;
}
 
void funTestObj(X&& robj) {
	std::cout << "run in funTestObj(X&& robj)" << std::endl;
}
 
void funt1120(X&& robj) {
	//X newobj = robj;  // 拷贝构造函数
	X newobj = std::move(robj);  // 拷贝构造函数
	//funTestObj(robj);
}
 
 
int main() {
	//X obj;
	X obj(1, 2);
 
	//funt1120(std::move(obj));
 
	X obj2 = std::move(obj); //移动构造函数
 
	return 0;
}

  

 

例如上面的版本,我们可以测试,当有这句时“X& operator=(const X&) = default;”,Nest类走的是拷贝构造;咩有的时候,能成功走移动。

 

posted @ 2024-11-21 11:16 xiarunliang 阅读(14) 评论(0) 推荐(0)
摘要: std::quoted 是干啥用的,有啥作用?看是c++14和17中加入的。 quoted 这个单词似乎在计算机里面就有着特殊的意思,可惜没记住。英文原版资料看的少。 在cppreference网站中的示例如下:(https://en.cppreference.com/w/cpp/io/manip/ 阅读全文
posted @ 2023-06-28 20:02 xiarunliang 阅读(342) 评论(0) 推荐(1)
摘要: 学习一个视频教程时说go里的switch中case是从上往下执行,直到一个case结果是true,开始执行其中的语句块。 之前学习的时候没注意到这个。以为是和c++一样是直接hash命中要执行的case。 试了下,结果是和视频中说的一致的。实验代码如下: func func2() bool { fm 阅读全文
posted @ 2021-11-04 16:10 xiarunliang 阅读(681) 评论(0) 推荐(0)
摘要: 正文: 最全的资料就是:https://gcc.gnu.org/onlinedocs/gcc/index.html 其他,或者在机子上 man或 --help之类。 正文结束,开始废话。 几次看书的过程中,都曾想应该整理、学习下gcc工具的一些知识。 在搜O1和 O3优化区别时,搜到了好几篇雷同的。 阅读全文
posted @ 2021-10-26 21:14 xiarunliang 阅读(59) 评论(0) 推荐(0)
摘要: 我是不是在以程序员的脑洞去考虑去除word的某种“底纹” 阅读全文
posted @ 2021-10-11 17:10 xiarunliang 阅读(314) 评论(0) 推荐(0)
摘要: 在线运行c++代码: http://cpp.sh/ 一些linux命令/参数解释: https://explainshell.com/ 摘录自 https://linux.cn/article-3940-1.html Linux manual page-在线man手册? https://man7.o 阅读全文
posted @ 2021-08-15 11:38 xiarunliang 阅读(888) 评论(0) 推荐(0)
摘要: 这里记录的并没什么新意,实质内容是几个参考资料的摘录和搬运,参考资料的几个链接中有比较详细的介绍。 而且资料可能有点老,有没真实的说明当下的准确情形,也不确定。 任务调度,当然是在多任务系统情况下才有的需求。 任务调度,其实是对于一个执行单元——线程——来说的,但一般也就笼统的说是进程或任务调度器。 阅读全文
posted @ 2021-07-11 18:18 xiarunliang 阅读(354) 评论(0) 推荐(0)
摘要: 引子 看进程调度时,介绍优先级相同时的一些特殊处理,说当候选多给进程优先级相同时,一些倾向选择,有提到候选的进程和之前执行的进程有相同的进程空间时,会被优先选择。 而什么时候会出现这种两个进程使用相同的进程空间呢,说了两种情况,一个很熟悉的就是两个调度对象是痛一个进程中的两个线程对象时。 另一个说的 阅读全文
posted @ 2021-07-11 14:42 xiarunliang 阅读(330) 评论(0) 推荐(0)
摘要: 头脑里整理了下刚搜索了解到一些介绍,准备简单记录下。又反观了下,似乎自己还是有着主观倾向的(虽然也就如同牢骚类的没啥卵用),似乎并不喜欢bfs。 可能并不是不喜欢这个东西,而是感觉那些相伴的东西,包括名字/出现形式/一些介绍描述/一些略显夸张的拥趸。 对cfs的批评诟病,为啥总让我联想到对c++的诟 阅读全文
posted @ 2021-07-10 14:24 xiarunliang 阅读(232) 评论(0) 推荐(0)
摘要: 可重载的操作符,摘录自c++ primer第四版 表14.1: + - * / % ^ & | ~ ! , = < > <= >= ++ -- << >> == != && || += -= /= %= ^= &= |= *= <<= >>= [] () -> ->* new new [] dele 阅读全文
posted @ 2021-06-05 19:32 xiarunliang 阅读(95) 评论(0) 推荐(0)
点击右上角即可分享
微信分享提示