Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
374 views
in Technique[技术] by (71.8m points)

c++ - 为什么要使用指针而不是对象本身?(Why should I use a pointer rather than the object itself?)

I'm coming from a Java background and have started working with objects in C++.

(我来自Java背景,已经开始使用C ++处理对象。)

But one thing that occurred to me is that people often use pointers to objects rather than the objects themselves, for example this declaration:

(但是我想到的一件事是,人们经常使用指向对象的指针,而不是对象本身,例如以下声明:)

Object *myObject = new Object;

rather than:

(而不是:)

Object myObject;

Or instead of using a function, let's say testFunc() , like this:

(或者不使用函数,而是说testFunc() ,如下所示:)

myObject.testFunc();

we have to write:

(我们必须写:)

myObject->testFunc();

But I can't figure out why should we do it this way.

(但是我不知道为什么我们要这样做。)

I would assume it has to do with efficiency and speed since we get direct access to the memory address.

(我认为这与效率和速度有关,因为我们可以直接访问内存地址。)

Am I right?

(我对吗?)

  ask by gEdringer translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It's very unfortunate that you see dynamic allocation so often.

(不幸的是,您经常看到动态分配。)

That just shows how many bad C++ programmers there are.

(这只表明有多少坏的C ++程序员。)

In a sense, you have two questions bundled up into one.

(从某种意义上说,您将两个问题捆绑在一起。)

The first is when should we use dynamic allocation (using new )?

(首先是何时应该使用动态分配(使用new )?)

The second is when should we use pointers?

(第二个是什么时候应该使用指针?)

The important take-home message is that you should always use the appropriate tool for the job .

(重要提示信息是您应始终使用适当的工具进行作业 。)

In almost all situations, there is something more appropriate and safer than performing manual dynamic allocation and/or using raw pointers.

(在几乎所有情况下,都比执行手动动态分配和/或使用原始指针更合适,更安全。)

Dynamic allocation (动态分配)

In your question, you've demonstrated two ways of creating an object.

(在您的问题中,您演示了两种创建对象的方法。)

The main difference is the storage duration of the object.

(主要区别是对象的存储时间。)

When doing Object myObject;

(当做Object myObject;)

within a block, the object is created with automatic storage duration, which means it will be destroyed automatically when it goes out of scope.

(在一个块内,将创建具有自动存储持续时间的对象,这意味着它将在超出范围时自动销毁。)

When you do new Object() , the object has dynamic storage duration, which means it stays alive until you explicitly delete it.

(当您执行new Object() ,对象具有动态存储持续时间,这意味着该对象将保持活动状态,直到您明确delete它为止。)

You should only use dynamic storage duration when you need it.

(您仅应在需要时使用动态存储期限。)

That is, you should always prefer creating objects with automatic storage duration when you can .

(也就是说, 您应该始终喜欢在可以的时候创建具有自动存储持续时间的对象 。)

The main two situations in which you might require dynamic allocation:

(您可能需要动态分配的两种主要情况:)

  1. You need the object to outlive the current scope - that specific object at that specific memory location, not a copy of it.

    (您需要使对象的寿命超出当前作用域 -该特定对象位于该特定内存位置,而不是其副本。)

    If you're okay with copying/moving the object (most of the time you should be), you should prefer an automatic object.

    (如果您可以复制/移动对象(大多数情况下应该如此),则应该使用自动对象。)

  2. You need to allocate a lot of memory , which may easily fill up the stack.

    (您需要分配大量内存 ,这很容易填满堆栈。)

    It would be nice if we didn't have to concern ourselves with this (most of the time you shouldn't have to), as it's really outside the purview of C++, but unfortunately, we have to deal with the reality of the systems we're developing for.

    (如果我们不必为此担心(大多数时候您不必担心),那将是很好的,因为它确实超出了C ++的范围,但是不幸的是,我们必须处理系统的实际情况。我们正在开发。)

When you do absolutely require dynamic allocation, you should encapsulate it in a smart pointer or some other type that performs RAII (like the standard containers).

(当您确实需要动态分配时,应将其封装在智能指针或其他执行RAII的类型中(例如标准容器)。)

Smart pointers provide ownership semantics of dynamically allocated objects.

(智能指针提供了动态分配对象的所有权语义。)

Take a look at std::unique_ptr and std::shared_ptr , for example.

(例如,看一下std::unique_ptrstd::shared_ptr 。)

If you use them appropriately, you can almost entirely avoid performing your own memory management (see the Rule of Zero ).

(如果正确使用它们,则几乎可以完全避免执行自己的内存管理(请参见零规则 )。)

Pointers (指针)

However, there are other more general uses for raw pointers beyond dynamic allocation, but most have alternatives that you should prefer.

(但是,除动态分配外,原始指针还有其他更通用的用法,但大多数都有您应首选的替代方法。)

As before, always prefer the alternatives unless you really need pointers .

(和以前一样, 除非您确实需要使用指针,否则请始终选择替代方法 。)

  1. You need reference semantics .

    (您需要参考语义 。)

    Sometimes you want to pass an object using a pointer (regardless of how it was allocated) because you want the function to which you're passing it to have access that that specific object (not a copy of it).

    (有时您想要使用指针传递对象(无论如何分配),因为您希望传递给它的函数可以访问该特定对象(而不是其副本)。)

    However, in most situations, you should prefer reference types to pointers, because this is specifically what they're designed for.

    (但是,在大多数情况下,您应该更喜欢引用类型而不是指针,因为这是专门为它们设计的。)

    Note this is not necessarily about extending the lifetime of the object beyond the current scope, as in situation 1 above.

    (请注意,这不一定是要延长对象的生存期,使其超出当前范围,如上述情况1所示。)

    As before, if you're okay with passing a copy of the object, you don't need reference semantics.

    (和以前一样,如果您可以传递对象的副本,则不需要引用语义。)

  2. You need polymorphism .

    (您需要多态性 。)

    You can only call functions polymorphically (that is, according to the dynamic type of an object) through a pointer or reference to the object.

    (您只能通过指针或对对象的引用来多态调用函数(即,根据对象的动态类型)。)

    If that's the behavior you need, then you need to use pointers or references.

    (如果这是您需要的行为,则需要使用指针或引用。)

    Again, references should be preferred.

    (同样,引用应该是首选。)

  3. You want to represent that an object is optional by allowing a nullptr to be passed when the object is being omitted.

    (您想通过允许在省略对象时传递nullptr 来表示该对象是可选的。)

    If it's an argument, you should prefer to use default arguments or function overloads.

    (如果是参数,则应该首选使用默认参数或函数重载。)

    Otherwise, you should preferably use a type that encapsulates this behavior, such as std::optional (introduced in C++17 - with earlier C++ standards, use boost::optional ).

    (否则,您最好使用一种封装此行为的类型,例如std::optional (在C ++ 17中引入-对于较早的C ++标准,请使用boost::optional )。)

  4. You want to decouple compilation units to improve compilation time .

    (您希望解耦编译单元以缩短编译时间 。)

    The useful property of a pointer is that you only require a forward declaration of the pointed-to type (to actually use the object, you'll need a definition).

    (指针的有用属性是,您只需要指向类型的前向声明(要实际使用该对象,您需要一个定义)。)

    This allows you to decouple parts of your compilation process, which may significantly improve compilation time.

    (这使您可以使编译过程的各个部分脱钩,从而可以大大缩短编译时间。)

    See the Pimpl idiom .

    (请参阅“ Pimpl习惯用法” 。)

  5. You need to interface with a C library or a C-style library.

    (您需要与C库或C样式库接口。)

    At this point, you're forced to use raw pointers.

    (在这一点上,您不得不使用原始指针。)

    The best thing you can do is make sure you only let your raw pointers loose at the last possible moment.

    (您可以做的最好的事情是确保仅在可能的最后时刻松开原始指针。)

    You can get a raw pointer from a smart pointer, for example, by using its get member function.

    (您可以从智能指针中获取原始指针,例如,通过使用其get成员函数。)

    If a library performs some allocation for you which it expects you to deallocate via a handle, you can often wrap the handle up in a smart pointer with a custom deleter that will deallocate the object appropriately.

    (如果库为您执行了一些分配,希望您可以通过句柄对其进行分配,则通常可以使用自定义删除程序将句柄包装在智能指针中,该删除器将适当地分配对象。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...