阅读git rebase
和git merge-base
人文档:
在使用git checkout -b topic origin/master创建的主题分支之后,远程跟踪分支origin/master的历史记录可能已经倒带和重建,从而导致了这种形状的历史记录:
Run Code Online (Sandbox Code Playgroud)o---B1 / ---o---o---B2--o---o---o---B (origin/master) \ B3 \ Derived (topic)
origin/master用于指向提交B3,B2,B1,现在它指向B,当origin/master位于B3时,您的主题分支在它上面启动.此模式使用origin/master的reflog来查找B3作为分叉点,以便可以通过以下方式在更新的origin/master之上重新定位主题:
Run Code Online (Sandbox Code Playgroud)$ fork_point=$(git merge-base --fork-point origin/master topic) $ git rebase --onto origin/master $fork_point topic
$fork_point
将(如果我理解正确的话)是提交对象B3
,因此提交B3..topic
将被重新绑定到origin/master
分支.
Q1为什么省略B3
提交有用?topic
分支的提交建立在B3
提交之上,因此省略它意味着它的修改将在origin/master
分支的故事中丢失.衍合的B3
提交与该topic
分支会导致一个更清洁的历史,是不是?
Q2有人可以链接/简要描述--fork-point
git工作流中该选项的实际用例吗?
§ 3.10.1.5
从标准定义prvalue
表达式为:
- prvalue("纯"rvalue)是一个不是xvalue的rvalue.[示例:调用返回类型不是引用的函数的结果是prvalue.诸如12,7.3e5或true之类的文字的值也是prvalue. - 结束例子]
因此该函数foo()
是一个prvalue
表达式:
class Foo {};
Foo foo() { return Foo{}; }
Run Code Online (Sandbox Code Playgroud)
要初始化lvalue reference to a non-volatile const type
/ rvalue reference
初始化表达式必须是(§ 5.2.1.1
):
[...] xvalue(但不是位字段),类prvalue,数组prvalue或函数lvalue和"cv1 T1"与"cv2 T2"引用兼容,或[...]
从而,
Foo &&rrFoo_ = foo();
Run Code Online (Sandbox Code Playgroud)
是有效的代码rrFoo_
绑定到延长对象生命周期的临时对象(§12.2
):
类型的临时数在各种上下文中创建:绑定对prvalue的引用(8.5.3),返回prvalue(6.6.3),创建prvalue的转换(4.1,5.2.9,5.2.11,5.4) ,抛出异常(15.1),并在一些初始化(8.5)中.
如上所述并且忽略了RVO,以下类型对象的初始化Foo
将复制移动构造临时从默认构造对象.然后用于复制move的临时对象构造名为的最终对象obj_foo
:
Foo obj_foo{ foo() };
Run Code Online (Sandbox Code Playgroud)
因此,在这两种情况下,我们要么偷窃,要么延长临时对象的生命周期,否则会被破坏.
§3.10.1.2
将xvalues定义为:
xvalue("eXpiring"值)也指对象,通常接近其生命周期的末尾(例如,可以移动其资源).[...]
我想不出任何没有创建临时对象的情况.所以我的问题是,为什么函数表达式foo()
被认为是prvalue
表达式,即使它们至少具有类似的属性 …
阅读anwser 有关在ac标识符中使用下划线的规则我偶然发现了下面的引文:
从2003 C++标准:
17.4.3.2.1全局名称[lib.global.names]
某些名称和函数签名集始终保留给实现:
- 每个包含双下划线(_ _)或以下划线后跟大写字母(2.11)开头的名称都保留给实现以供任何使用.
- 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称.165
165)这些名称也在namespace :: std(17.4.3.1)中保留.
保留用于实现的确切含义是什么?
根据维基百科,执行模型是
语言规范的一部分,并作为语言实现的一部分来实现。
它进一步定义了
执行顺序可以静态选择[...],但一小部分必须在执行过程中动态选择。
[...] 静态选择通常在编译器内部实现,在这种情况下,工作顺序由指令放入可执行二进制文件的顺序表示。然后,动态选择将在语言的运行时系统内实现。
运行时系统可以是一个库,由编译器插入的指令调用,或者运行时系统可以直接嵌入到可执行文件中,例如通过插入分支指令,这对下一步要执行的工作进行动态选择。
维基百科将运行时系统指定为
任何不直接由程序工作的行为都是运行时系统行为。该定义包括运行时系统的一部分,例如在函数调用之前将参数放入堆栈、磁盘 I/O 的行为以及与并行执行相关的行为。
另外
也是正在运行的程序与运行时环境交互的网关,它不仅包含程序执行期间可访问的状态值,还包含程序执行期间可通过键盘交互的活动实体,例如磁盘驱动器和人。
它进一步指出,
运行时系统实现的更高级别的行为可能包括诸如在屏幕上绘制文本或建立互联网连接之类的任务。
通常情况下,操作系统也提供这些类型的行为[...]运行时系统被实现为抽象层,它将运行时系统的调用转换为操作系统的调用。这隐藏了不同操作系统提供的服务的复杂性或变化。[对于我来说,关于 Linux 内核,这基本上是系统调用]
这也意味着操作系统内核本身可以被视为运行时系统,并且调用操作系统行为的操作系统调用集可以被视为与运行时系统的交互。
我知道必须有某种运行时环境,例如 Linux 内核,将编译后的可执行文件加载到内存中,启动进程,允许子线程之类的东西。内核本身是用语言编写的C
,不能被视为C
语言的“运行时系统”。然而,它提供了诸如malloc()
和 之类的功能free()
,这些功能是运行时系统的重要组成部分。
Q那么到底什么是运行时系统呢C
?有没有一个不模糊的定义?它是独立内核+编译器的混合物吗?
给出代码片段:
struct S {
static const int var = 0;
};
int function(const int& rVar){
return rVar;
}
int main()
{
return function(S::var);
}
Run Code Online (Sandbox Code Playgroud)
编译gcc 5.4.0
:
g++ -std=c++17 main.cpp -o test
Run Code Online (Sandbox Code Playgroud)
导致以下链接错误:
/tmp/ccSeEuha.o: In function `main':
main.cpp:(.text+0x15): undefined reference to `S::var'
collect2: error: ld returned 1 exit status
§3.3
来自ISO标准C++ 17草案n4296
规定:
变量x的名称显示为潜在评估的表达式ex,除非将lvalue-to-rvalue转换(4.1)应用于x,产生不调用任何非平凡函数的常量表达式(5.20),否则由ex使用odr. ,如果x是一个对象,ex是表达式e的潜在结果集的一个元素,其中左值到右值的转换(4.1)应用于e [ 粗体格式添加],或者e是丢弃值表达式(第5条).
问:为什么var
这里需要变量的定义?不var
表示出现在outter函数调用表达式的潜在评估表达式S::var
中的整数对象,它实际上通过引用获取参数,但最终应用了左值到右值的转换,因此不是如段落所述使用的odr?
鉴于源代码 strcpy()
char * strcpy(char *s1, const char *s2)
{
char *s = s1;
while ((*s++ = *s2++) != 0);
return (s1);
}
Run Code Online (Sandbox Code Playgroud)
为什么移交第二个参数有效,以及它如何在内存中查找,因为我没有传递指向函数的指针
char dest[100];
strcpy(dest, "HelloWorld");
Run Code Online (Sandbox Code Playgroud) free
在堆上分配内存后,这两种调用变量之间是否存在差异:
// variant 1
int* p1 = (int*) malloc(sizeof(int)*4);
free(p1);
//variant 2
int* p2 = (int*) malloc(sizeof(int)*4);
free(*p2);
*p2 = NULL;
Run Code Online (Sandbox Code Playgroud)