指针的额外好处,何时使用,为什么使用 我现在正在学习C++,虽然我掌握了指针和引用的概念,但有些事情并不清楚。 假设我有以下代码(假设矩形有效,实际代码并不重要): #包括 #包括“矩形.h” 无效变更(矩形和rec); int main() { 矩形矩形; 矩形集合x(50); 矩形集y(75); std::cout
指针的额外好处,何时使用,为什么使用 我现在正在学习C++,虽然我掌握了指针和引用的概念,但有些事情并不清楚。 假设我有以下代码(假设矩形有效,实际代码并不重要): #包括 #包括“矩形.h” 无效变更(矩形和rec); int main() { 矩形矩形; 矩形集合x(50); 矩形集y(75); std::cout,c++,reference,pointers,oop,C++,Reference,Pointers,Oop,rectwo与rect的不同之处在于rect是堆栈上Rectangle的一个实例,而rectwo是堆上Rectangle的地址。如果按值传递Rectangle,则会生成它的一个副本,并且您将无法进行任何更改不在changestuff()的范围内 通过引用传递它意味着changestuff将具有矩形实例本身的内存地址,并且更改不限于changestuff的范围(因为矩形) 编辑:您的评论使问题更加清晰。一般来说,引用比指针更安全 来自维基百科: 在引用对象创建之后,不可能直接引用该对象 定义的;其
rectwo
与rect
的不同之处在于rect
是堆栈上Rectangle
的一个实例,而rectwo
是堆上Rectangle
的地址。如果按值传递Rectangle
,则会生成它的一个副本,并且您将无法进行任何更改不在changestuff()的范围内
通过引用传递它意味着changestuff
将具有矩形
实例本身的内存地址,并且更改不限于changestuff
的范围(因为矩形
)
编辑:您的评论使问题更加清晰。一般来说,引用比指针更安全
来自维基百科:
在引用对象创建之后,不可能直接引用该对象
定义的;其名称的任何出现
直接指它所属的对象
参考资料
一旦创建了引用,以后就无法对其进行引用
另一个对象;无法重置它。
这通常是通过指针完成的
引用不能为null,而指针可以;每个引用都引用
对于某个对象,尽管它可能或可能
无效
无法取消初始化引用。因为无法
重新初始化引用时,它们必须
一旦它们被初始化
创建。特别是本地和
必须初始化全局变量
定义它们的位置,以及引用
哪些是类的数据成员
实例必须在
类的初始值设定项列表
构造器
此外,在堆上分配的对象可能导致内存泄漏,而在堆栈上分配的对象则不会
因此,在必要时使用指针,否则使用引用。rectwo
与rect
的不同之处在于rect
是堆栈上的Rectangle
的一个实例,而rectwo
是堆上的Rectangle
的地址。如果通过值传递Rectangle
,则为它已创建,您将无法进行changestuff()
范围之外的任何更改
通过引用传递它意味着changestuff
将具有矩形
实例本身的内存地址,并且更改不限于changestuff
的范围(因为矩形
)
编辑:您的评论使问题更加清晰。一般来说,引用比指针更安全
来自维基百科:
在引用对象创建之后,不可能直接引用该对象
定义的;其名称的任何出现
直接指它所属的对象
参考资料
一旦创建了引用,以后就无法对其进行引用
另一个对象;无法重置它。
这通常是通过指针完成的
引用不能为null,而指针可以;每个引用都引用
对于某个对象,尽管它可能或可能
无效
无法取消初始化引用。因为无法
重新初始化引用时,它们必须
一旦它们被初始化
创建。特别是本地和
必须初始化全局变量
定义它们的位置,以及引用
哪些是类的数据成员
实例必须在
类的初始值设定项列表
构造器
此外,在堆上分配的对象可能导致内存泄漏,而在堆栈上分配的对象则不会
这样,在需要时使用指针,否则引用。
< p>您需要了解引用不是指针。它们可以使用它们实现(或者它们可能不),但是C++中的引用与指针完全不同。
也就是说,任何引用了指针的函数都可以通过解引用(反之亦然)与指针一起使用。给定:
你可以说:
A a;
f1( a )
f2 ( &a );
以及:
什么时候应该使用哪一种?这取决于经验,但一般的良好实践是:
- 尽可能在堆栈上自动分配对象,而不是使用
new
- 尽可能使用引用(最好是常量引用)传递对象
你需要理解引用不是指针。它们可以使用它们实现(或者它们不可以),但是C++中的引用与指针完全不同。
也就是说,任何引用了指针的函数都可以通过解引用(反之亦然)与指针一起使用。给定:
你可以说:
A a;
f1( a )
f2 ( &a );
以及:
什么时候应该使用哪一种?这取决于经验,但一般的良好实践是:
- 尽可能在堆栈上自动分配对象,而不是使用
new
- 尽可能使用引用(最好是常量引用)传递对象
你没有任何理由。在C中,你只有指针。C++引入引用,通常C++中的首选方式是通过引用。它产生更简洁的语法,更简单。
让我们使用您的代码并向其中添加一个新函数:
#include <iostream>
#include "Rectangle.h"
void changestuff(Rectangle& rec);
void changestuffbyPtr(Rectangle* rec);
int main()
{
Rectangle rect;
rect.set_x(50);
rect.set_y(75);
std::cout << "x,y: " << rect.get_x() << rect.get_y() << sizeof(rect) << std::endl;
changestuff(rect);
std::cout << "x,y: " << rect.get_x() << rect.get_y() << std::endl;
changestuffbyPtr(&rect);
std::cout << "x,y: " << rect.get_x() << rect.get_y() << std::endl;
Rectangle* rectTwo = new Rectangle();
rectTwo->set_x(15);
rectTwo->set_y(30);
std::cout << "x,y: " << rectTwo->get_x() << rectTwo->get_y() << std::endl;
changestuff(*rectTwo);
std::cout << "x,y: " << rectTwo->get_x() << rectTwo->get_y() << std::endl;
changestuffbyPtr(rectTwo);
std::cout << "x,y: " << rectTwo->get_x() << rectTwo->get_y() << std::endl;
std::cout << rectTwo << std::endl;
}
void changestuff(Rectangle& rec)
{
rec.set_x(10);
rec.set_y(11);
}
void changestuffbyPtr(Rectangle* rec)
{
rec->set_x(10);
rec->set_y(11);
}
虽然这不是:
int& b;
引用必须引用某些内容。这使得引用在多态情况下基本上不可用,在这种情况下,您可能不知道指针初始化到什么位置。例如:
// let's assume A is some interface:
class A
{
public:
void doSomething() = 0;
}
class B : public A
{
public:
void doSomething() {}
}
class C : public A
{
public:
void doSomething() {}
}
int main()
{
// since A contains a pure virtual function, we can't instantiate it. But we can
// instantiate B and C
B* b = new B;
C* c = new C;
// or
A* ab = new B;
A* ac = new C;
// but what if we didn't know at compile time which one to create? B or C?
// we have to use pointers here, since a reference can't point to null or
// be uninitialized
A* a1 = 0;
if (decideWhatToCreate() == CREATE_B)
a1 = new B;
else
a1 = new C;
}
没有任何理由你不能。在C中,你只有指针。C++介绍
#include <iostream>
#include "Rectangle.h"
Rectangle* createARect1();
Rectangle* createARect2();
int main()
{
// this is being created on the stack which because it is being created in main,
// belongs to the stack for main. This object will be automatically destroyed
// when main exits, because the stack that main uses will be destroyed.
Rectangle rect;
// rectTwo is being created on the heap. The memory here will *not* be released
// after main exits (well technically it will be by the operating system)
Rectangle* rectTwo = new Rectangle();
// this is going to create a memory leak unless we explicitly call delete on r1.
Rectangle* r1 = createARectangle();
// this should cause a compiler warning:
Rectangle* r2 = createARectangle();
}
Rectangle* createARect1()
{
// this will be creating a memory leak unless we remember to explicitly delete it:
Rectangle* r = new Rectangl;
return r;
}
Rectangle* createARect2()
{
// this is not allowed, since when the function returns the rect will no longer
// exist since its stack was destroyed after the function returns:
Rectangle r;
return &r;
}
int *b;
int& b;
// let's assume A is some interface:
class A
{
public:
void doSomething() = 0;
}
class B : public A
{
public:
void doSomething() {}
}
class C : public A
{
public:
void doSomething() {}
}
int main()
{
// since A contains a pure virtual function, we can't instantiate it. But we can
// instantiate B and C
B* b = new B;
C* c = new C;
// or
A* ab = new B;
A* ac = new C;
// but what if we didn't know at compile time which one to create? B or C?
// we have to use pointers here, since a reference can't point to null or
// be uninitialized
A* a1 = 0;
if (decideWhatToCreate() == CREATE_B)
a1 = new B;
else
a1 = new C;
}