我正在研究指针参考,并提供了不同的方式来提供参数。有人可以解释每个人的实际含义吗?
我认为第一个很简单,就是x
是所输入参数的副本,因此在堆栈上创建了另一个变量。
至于其他人,我很无能为力。
void doSomething1(int x){
//code
}
void doSomething2(int *x){
//code
}
void doSomething3(int &x){
//code
}
void doSomething3(int const &x){
//code
}
当声明变量时,我也会看到这样的东西。我不明白他们之间的差异。我知道第一个会将100
放入堆栈中的变量y
。它不会创建新地址或其他任何内容。
//example 1
int y = 100;
//example 2
int *y = 100;
//Example 3: epic confusion!
int *y = &z;
问题1:我如何使用这些方法?什么时候最合适?
问题2:我何时以这种方式声明变量?
例子很棒。
P.S。这是我没学习C ++的主要原因之一,因为Java只有垃圾收集。但现在我必须进入C ++。
答案 0 :(得分:10)
//example 1 int y = 100; //example 2 int *y = 100; //Example 3: epic confusion! int *y = &z;
我认为大多数学生的问题是在C ++中,&
和*
具有不同的含义,具体取决于使用它们的上下文。
如果其中任何一个在对象声明 (T*
或T&
)中的类型后出现 ,则它们是 类型修饰符 并将类型从普通T
更改为 对T
(T&
)的引用或 指向T
(T*
) 的指针。
如果它们在对象前面显示 (&obj
或*obj
),则它们是 一元前缀运算符 在对象上调用。前缀&
会返回调用它的对象的 地址 ,*
取消引用 指针,迭代器等,产生它引用的值。
对于混淆,类型修饰符适用于所声明的对象而不是类型无效。也就是说,T* a, b;
定义了一个名为T*
的{{1}}和一个名为a
的普通T
,这就是为什么许多人更喜欢编写b
(注意类型修改T *a, b;
的位置与正在定义的对象相邻,而不是修改的类型。
同样无益的是术语“引用”过载。一方面,它意味着一个句法结构,如*
。但是,“参考”的更广泛含义是指其他东西。从这个意义上讲,指针T&
和引用(其他含义T*
)都是引用,因为它们引用了一些对象。当有人说“指针引用某个对象”或指针被“取消引用”时,它就会发挥作用。
因此,在您的特定情况下,#1定义了普通T&
,#2定义了指向int
的指针,并使用地址int
对其进行初始化(无论生命中最好的是什么)保持不变),#3定义另一个指针并使用对象100
的地址(也必须是z
)对其进行初始化。
关于如何将对象传递给C ++中的函数, here 是我的回答。
答案 1 :(得分:4)
来自Scott Myers - 更有效的C ++ - > 1
首先,要认识到没有空引用这样的东西。引用必须始终引用某个对象。因为引用必须引用对象,所以C ++需要初始化引用。
指针不受此限制。事实上,没有空引用这样的事实意味着使用引用比使用指针更有效。这是因为在使用之前无需测试参考的有效性。
指针和引用之间的另一个重要区别是指针可能会被重新分配以引用不同的对象。但是,引用始终引用用于初始化的对象
一般情况下,只要你需要考虑没有什么可引用的可能性(在这种情况下你可以将指针设置为null)或者你需要能够引用不同的东西时,你应该使用指针在不同的时间(在这种情况下,您可以更改指针指向的位置)。只要你知道总会有一个对象可以引用你就应该使用引用,并且你也知道,一旦你引用了那个对象,你就永远不想引用任何其他东西了。
当你知道你有什么需要引用时,引用是你选择的特性,当你永远不想引用任何其他内容时,以及当实现其语法要求使得指针的使用不合需要的运算符时。在所有其他情况下,坚持使用指针。
答案 2 :(得分:2)
阅读S.Lippmann的C ++ Premier或任何其他优秀的C ++书籍。 至于传递参数,通常在复制便宜时我们通过值。对于强制输出参数,我们使用引用,对于可选输出参数 - 指针,对于复制成本高昂的输入参数,我们通过const引用
答案 3 :(得分:1)
这真的很复杂。请在此处阅读:http://www.goingware.com/tips/parameters/。 Scott Meiers的“Effective C ++”也是这本书的顶级书。
答案 4 :(得分:1)
void doSomething1(int x){ //码 } 这个通过值传递变量,无论函数内部发生什么,原始变量都不会改变
void doSomething2(int * x){ //码 } 在这里,您将类型指针的变量传递给整数。因此,当访问该数字时,您应使用* x作为值,或使用x作为地址
void doSomething3(int& x){ //码 } 这就像第一个,但无论函数内部发生什么,原始变量也将被更改
int y = 100; 正常整数
//示例2 int * y = 100; 指向地址100的指针
//示例3:史诗混乱! int * y =& z; 指向z
地址的指针答案 5 :(得分:1)
void doSomething1(int x){
//code
}
void doSomething2(int *x){
//code
}
void doSomething3(int &x){
//code
}
我真的在他们之间感到困惑?
第一个是使用pass-by-value,函数的参数将在调用后保留其原始值。
后两个使用pass-by-reference。从本质上讲,它们是实现同样目标的两种方式。在电话会议结束后保留其原始价值并不保证这一论点。
大多数程序员喜欢通过const引用传递大对象来提高代码的性能,并提供值不会改变的约束。这可以确保不调用复制构造函数。
你的困惑可能是因为'&'算子有两个含义。您似乎熟悉的是“参考运算符”。它也用作'地址运算符'。在您给出的示例中,您将获取z的地址。
安德鲁·科宁(Andrew Koening)的“加速C ++”是一本很好的书,其中详细介绍了所有这些内容。
答案 6 :(得分:0)
使用这些方法的最佳时机是传递引用而不是整个对象更有效。有时,某些数据结构操作使用引用(例如插入链接列表)也更快。理解指针的最好方法是阅读它们然后编写程序来使用它们(并将它们与它们的按值传递对应物进行比较)。
为了记录,指针的知识使你在工作场所更有价值。 (通常情况下,C ++程序员是办公室的“神秘主义者”,知道办公桌下的那些神奇的盒子如何处理代码/半讽刺)