1

《C++ Primer》关于 reference 和 pointer 部分看的人“生气”

 2 years ago
source link: https://www.v2ex.com/t/840451
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  C++

《C++ Primer》关于 reference 和 pointer 部分看的人“生气”

  vcfghtyjc · 7 小时 14 分钟前 · 2217 次点击

对 C++一直是一知半解。最近正式的重读《 C++ Primer 》,不知道为什么看到 reference 和 pointer (章节:2.3 )莫名的生气。

不理解当初设计 C++的人多喜欢“&” 和 “*” 这两个符号。为什么不同功能要用同样的符号啊?!"&" 放在定义处代表引用,放到定义过的变量前代表取地址。键盘上那么多符号,就不能换个符号吗?当初大学 C++学的不好这个设计要背一半的锅。😂

40 条回复    2022-03-15 19:26:52 +08:00

Mohanson

Mohanson      7 小时 11 分钟前   ❤️ 9

学 Rust 吧, 只要键盘上能打出的符号在 Rust 里都被用作 token 了.

yzbythesea

yzbythesea      7 小时 10 分钟前

& 是这个变量的地址,* 是这个指针地址里的内容。不太明白“代表引用”的含义,& 在定义处也是取址吧。

learningman

learningman      7 小时 10 分钟前

那我就想传个指针,是不是传成指针的引用了多一次操作?
有聪明的啊,Go 加不加*一个语义,去吧(

smallthing

smallthing      7 小时 7 分钟前 via iPhone   ❤️ 6

笑死了,根本就是不懂

codehz

codehz      7 小时 3 分钟前 via Android

(问就是 c 遗产(
因为*已经用来表示指针和解引用了,&已经用来表示取地址了,你还能用别的什么符号来表示引用吗

l00t

l00t      6 小时 59 分钟前

这是延续 C 的风格吧, * 本身不也有好几个意思吗? 声明和定义的时候表示指针,实际用的时候表示指针指向。这都是小事了。

extern ,static 那一堆才看着烦。

darklights

darklights      6 小时 57 分钟前 via Android

相信我,就算换了个符合,大学 C++该学不好的还是学不好。

statumer

statumer      6 小时 56 分钟前   ❤️ 12

等你学深了,就知道 C++ 的引用符号还只是小事
我看楼主应该还没被 glvalue, prvalue, xvalue, lvalue, 右值引用, 引用的 value category 折磨过

dobelee

dobelee      6 小时 53 分钟前 via iPhone

golang 解君愁。

vcfghtyjc

vcfghtyjc      6 小时 50 分钟前

@statumer 刚看到里面提到 l-value, r-value 。看了两眼就先搁置了。。。

ChaosesIb

ChaosesIb      6 小时 49 分钟前 via Android

这只能说是理解不同,引用参数起的作用类似于传参时自动加&,那么把&加到参数声明处代表自动取址也就很自然了。语言对于引入新符号 /关键字总是保守的,历史包袱很重的 C++就更是这样了。

hhjuteman

hhjuteman      6 小时 45 分钟前   ❤️ 2

就这你就不行了啦?

来一段模版类型推导折叠规则:
T& & => 什么类型?
T& && => 什么类型?
T&& & => 什么类型?
T&& && => 什么类型?


你要是连 reference 的符号都觉得绕,劝你早日放弃 c++。

yulon

yulon      6 小时 44 分钟前

你要明白 C 和 C++ 是两个语言,设计引用的时候没有什么特别方便的语法,只能硬性规定声明里的 & 是引用。

C 的声明满足 [左边结果类型,右边表达式] ,右边的所有符号其实是操作符不是修饰符。

C++ 是怎么方便怎么来了,声明里的 & 确实算是修饰符了,还有 using type ,你用 typedef 多重嵌套的函数指针会想死的。

Huelse

Huelse      6 小时 42 分钟前

个人认为 C++中左右值和转移语义最重要且实用

Kasumi20

Kasumi20      6 小时 41 分钟前

不都是指针?引用让程序员减少了一步解引用而已

zvl0reqglvd

zvl0reqglvd      6 小时 41 分钟前

初学者还是不要找虐了。。。。

vcfghtyjc

vcfghtyjc      6 小时 36 分钟前

@yulon 感觉这个解释让我比较容易理解。你这里的的左边是这个意思吗?

int [左边] variable_name [右边]

所以当 "&" 在左边时是用来表述类型,当 "&" 在右边时表示操作符(取地址)。

littlewing

littlewing      6 小时 31 分钟前

@vcfghtyjc 智能指针、右值引用、移动语义、完美转发,这都是现代 C++ 的重要特性,不学这些等于没学现在 C++

littlewing

littlewing      6 小时 29 分钟前   ❤️ 1

C++ Primer 那本书不用看得太细,很多地方都太细节了

另外,你要多写写就懂了,光看是不行的

推荐 《 Effective Modern C++》这本书

vcfghtyjc

vcfghtyjc      6 小时 28 分钟前

@littlewing 多谢指出。等我慢慢看。

dongcidaci

dongcidaci      6 小时 23 分钟前 via Android

冷静一下,其实你会发现也没有那么难理解

jasonkayzk

jasonkayzk      6 小时 4 分钟前

杰哥:我看你是完全不懂喔~( doge

freeup

freeup      5 小时 56 分钟前

最近我也在看 C++这本书 对于这块感觉还好 还是满能接受的 估计是因为之前 C#中使用简单的指针操作也是这两个符号吧

crackhopper

crackhopper      5 小时 48 分钟前

python 的**在行参和实参,行为还不一样呢。。当然还是 C++更变态点,建议汇编水平高了,结合编译的汇编来看,帮忙加深理解。

我个人觉得 C++难以理解的有 memory_order...反正看 cpp reference 只会看晕,还涉及缓存可见、缓存一致。模板我学得也比较差,大概皮毛吧,主要不写库没空搞,也就掌握到 reference collapse 和一些实例化流程方面了解一点。abi 也不够了解,我个人觉得 abi 问题可以用汇编解决,但也没去深入研究过。链接机制虽然知道,但没有在源码层面有了解。elf 格式了解的也比较皮毛。我觉得基本 c/c++还是要配合汇编、操作系统、CPU 、GPU 等等一起学,加深理解。如果用不上这些,也没必要用 c/c++,其他语言更方便。

crackhopper

crackhopper      5 小时 41 分钟前

当然,如果 C++比较熟练,其实写起来也挺快的。一般自己都会积累常用的轮子和自己造的轮子。适用于特定领域。
按照 linus 的说法是,C++很可能不同人掌握的深入不一样,会有大量的沟通成本。因为 c++一些行为是隐式的,所以他更推崇 c 。有一定道理,但 c 写起来会麻烦点,需要把轮子重新造一遍。可能 c++最大的问题就是如何控制参与项目的人所掌握的深度,和开发中所使用的深度。(毕竟:C++ makes it harder to shoot yourself, but when you do it blows your whole leg off )
如果只是应用层级的开发,不涉及硬件,不设计高性能计算,换语言更好吧,毕竟即使不同人掌握的深度深浅不一也不会造成太大的灾难。

dongfang

dongfang      5 小时 40 分钟前

你说的引用符号是不会出现混淆的。
因为是声明的时候用,int& 是引用。
指针是这样子,int*。
完全不会混淆。
上面都是声明的时候,作为声明的类型。
&作为一目运算符,是取地址。
&作为两目运算符,是按位与。
*作为一目运算符,是对指针取值。
*做为两目运算符,是乘法。
也不会混淆,绝大多数情况下,语义是明确的。
可能出现混淆的时候,要加括号,比如
a*(*ptr)。这样别人也很容易看出,第一个*是乘法,第二个是对指针取值。
C++里面&和*的多重的语义,我个人是感觉没问题的。
反倒是,像 golang 里面的 switch 的多重语义放在一起,我感觉不是很好。
另外,如果你觉得引用类型声明的时候,不用&这个符号,你想用键盘上的哪个呢?
int$这样子,还是 int@这样子?感觉都挺丑的,还不如 int&。

SingeeKing

SingeeKing      5 小时 36 分钟前

@Mohanson #1 perl 不服 [手动狗头]

newmlp

newmlp      5 小时 35 分钟前

引用其实就是指针,不过就是个语法上有区别

dongfang

dongfang      5 小时 24 分钟前

再多说一点,*和&混用,一般也不会混淆。
比如,
int* & a = ptr;
这里的 a 是对指针类型 int*的引用。
int& * a; 这个是无法编译的。
不能定义一个指向引用的指针。

dongfang

dongfang      5 小时 14 分钟前

还有一点,从语义上,引用和指针没有任何关系。
引用是引用,指针是指针。
编译器在底层可以通过指针去实现引用这个功能,但是这并不是标准的规定。
从语义上,引用是取一个变量的别名,指针是内存中的地址。
所以,引用可以在内存中没有地址,一种很简单的思路,
就比如 int& a = b;
直接用#define a b 来实现。
也不是不可以。只不过这没法实现引用的其他功能。

dongfang

dongfang      5 小时 8 分钟前

如果你在语义上,无法区分引用和指针。
那后面的左值引用、右值引用,移动语义就搞不明白了。
有了这些东西能避免很多时候的拷贝开销。
用指针也可以实现这些优化,但是太繁琐了,不够现代

Tianqi

Tianqi      3 小时 20 分钟前

C++为了兼容 C 语言和向后兼容做了很多妥协

wffnone

wffnone      3 小时 10 分钟前

你生气发帖的时候,别人已经学下一节了。

fpure

fpure      2 小时 54 分钟前

C 语言的变量声明的规则类似模式匹配,C++的引用显然违背了这个规则

exonuclease

exonuclease      1 小时 46 分钟前

cpp 控制的东西太细节了所以符号看起来乱七八糟的 不过至少同样的功能 c#的语法好看一点
public struct Point3D
{
private static Point3D origin = new Point3D(0,0,0);
public static ref readonly Point3D Origin => ref origin; // static const Point3D& Origin = origin;
}

cybird

cybird      1 小时 42 分钟前

?????
指针是指针、引用是引用、右值是右值、左值是左值、表达式是表达式。

GeruzoniAnsasu

GeruzoniAnsasu      1 小时 41 分钟前

@hhjuteman 我 tm 直接按着编译器的头让它吐个报错来告诉我(恼

exonuclease

exonuclease      1 小时 33 分钟前

@exonuclease 好久不写 cpp 好像写错了 这里应该只有声明 static const Point3D& Origin

leirenbb

leirenbb      1 分钟前 via iPhone

那你还能说 c++不如都搞成指针 再加上 gc 之类的。不要玩什么栈变量呢🤣

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK