我知道point-to( - >)和dot(。)运算符之间的区别但是我不明白为什么需要两个arrises?是不是总是那么容易不使用指针而只是使用点运算符?来自http://www.programcreek.com/2011/01/an-example-of-c-dot-and-arrow-usage/
#include <iostream>
using namespace std;
class Car
{
public:
int number;
void Create()
{
cout << "Car created, number is: " << number << "\n" ;
}
};
int main() {
Car x;
// declares x to be a Car object value,
// initialized using the default constructor
// this very different with Java syntax Car x = new Car();
x.number = 123;
x.Create();
Car *y; // declare y as a pointer which points to a Car object
y = &x; // assign x's address to the pointer y
(*y).Create(); // *y is object
y->Create();
y->number = 456; // this is equal to (*y).number = 456;
y->Create();
}
为什么要费心使用指针?只需创建Y作为X,它将工作相同。如果你说你需要动态分配内存的指针,那么为什么还要使用点运算符?
答案 0 :(得分:6)
我认为你在混合两个不同的问题。
首先,->
运算符是不必要的,是的。 x->y
相当于(*x).y
,但->
运算符更容易输入,因此它基本上只是一种便利。
第二部分是指是否使用指针。 而你是对的,通常你不应该。默认情况下,只需创建您的对象,然后引用它们直接:
Foo bar;
bar.baz():
但很多情况下指针仍然是必需的。对象需要能够引用其他对象。引用可以做到这一点,但不能重新安装。一旦初始化,它将始终指向同一个对象。
可以更新指针以指向不同的对象。
链接列表,树数据结构和无数其他东西取决于能够指向其他对象的对象。
所以是的,我们需要指针。但我们需要 ->
运算符。我们只是使用它,因为它很方便。
答案 1 :(得分:2)
一个。它只是让语言更容易理解代码,而无需查看类型,或者使用m_pszMyName
之类的特殊符号。您可以立即告诉读代码什么是指针以及什么是值。
湾想想shared_ptr和覆盖运算符的情况。 shared_ptr<T>->get()
表示除shared_ptr<T>.get()
之外的其他内容。第一个是尖头对象中的函数,第二个是shared_ptr类本身的函数。这只是一个例子,但你明白了这一点。
答案 2 :(得分:1)
从您的链接:
以下示例应该是一个很好的例子。
实际上有点令人困惑。为什么要在堆栈上创建一个对象(Car x;
)然后创建一个指向它的指针以使用->
来访问它?
而不是试图回答隐含的问题“为什么我们需要指针?”我会尽力澄清那个例子可能引起的混乱。
在评论中你说:
我想知道创建的对象之间是否存在差异。
在示例中,只有一个对象,Car
创建的堆栈上的Car x;
(要完成,还有一个Car
- 指针在堆栈上,由Car *y;
创建。 <{1}}退出时,它们会超出范围,因此会清理它们的内存。
但是还有另一种创建对象的方法,我想你已经根据你的评论了解了这一点,这就是使用main()
在堆上初始化它们:{{ 1}}。堆上的对象永远不会超出范围,因此您可以在调用new
的函数退出后继续使用它们,但必须使用Car *z = new Car;
显式清除它们以防止内存泄漏。
因此,更实际地使用指向对象的指针:new
的返回值。
答案 3 :(得分:0)
像其他高阶语言一样,C / C ++没有用一些糖涂层语法封装指针。指针自然出现,下面的列表并非详尽无遗不是总是那么容易不使用指针而只是使用点 操作
从C ++角度来看,以上所有内容都可以封装到对象中。
尽管如此,指针甚至存在于您没有明确看到它们的语言中。它们只是封装到更高阶的对象。
这在某种程度上解释了为什么我们不能超越指针思考,下一部分你可能感兴趣的是语法。为什么我们需要ptr->somemember
而不是(*ptr).somemember
。
它只是重复使用的简写。 C / C ++程序员已经习惯了它,到目前为止我还没有看到使用多余语法的单个程序。
答案 4 :(得分:0)
- &GT;简而言之。考虑一个类表示树的节点:
struct node {
int data;
node* left;
node* right;
};
成员left
是指向节点左子节点的指针。假设我们有一个指向某个节点p
的指针,现在我们想让指针指向p的左子节点的左子节点的右子节点,使用点我们必须写(*(*(*p).left).left).right
,这很困难阅读和容易出错,使用 - &gt;我们可以简单地写一下p->left->left->right
,非常清楚。
答案 5 :(得分:0)
C ++中->
和.
运算符的存在是C的直接影响.C区分通过指针访问对象和访问当前作用域中声明的对象
在C ++中,引用是访问本地作用域对象的自然扩展。
我不知道C的创作者是否考虑过这一点,但我总是将其用作小型优化指南。查看一段代码,您可以看到->
将在运行时计算最终地址,而.
运算符将在编译时计算地址。这甚至可以在访问结构成员时起作用。请考虑以下事项:myptr->mMember.mValue
可以在编译时计算从mMember到mValue的偏移量,而必须在运行时计算指针的最终地址计算。我承认,就优化问题而言,这是一个很小的考虑因素,并且在C ++中引用它已经不可能做到这一点了,但是20年前它还是要记住的。
答案 6 :(得分:0)
是的,您可以随时使用(*x).member
代替x->member
,但是当x
是一个复杂的表达式时,您真的想要吗?
相关的东西(在这种情况下为*
和.
)远远会使源代码的可读性降低,因此将->
“放在一个地方”只是一种更好的语法。
至于需要指针的概念,主要有两个原因:
分配对象有两种方法
当执行流程进入和退出函数时,堆栈会卷绕和展开,因此堆栈对象的生命周期不可避免地与我们在创建它的函数中停留的时间有关。
如果你需要一个比创建它的函数更长的对象,你需要在动态内存中创建它,而 only 方式来识别这样的对象是通过它的内存地址,又名。指针。
是否有多个其他对象需要访问该对象?如果是,则这些其他对象无法引用共享对象其他而不是保留其地址。
即使您只有一个其他对象,但它们的生命周期不同,“生命周期”原因也适用。 如果,只有一个其他对象和的生命周期匹配,而不是将其作为字段。