简体   繁体   English

在 C++ 中,对象和指向对象的指针有什么区别?

[英]in C++, what's the difference between an object and a pointer to an object?

In java and objective-c, a variable representing an object is generally a pointer to that object.在java和objective-c中,表示对象的变量一般是指向该对象的指针。 However, it seems that in C++, it's common to have non-pointer types hold objects.但是,在 C++ 中,非指针类型保存对象似乎很常见。 What's the difference between the two?两者有什么区别?

If I pass a struct as an argument to a function, I believe I'm passing by value, meaning I'm actually creating a new struct in memory, and changes to that struct inside the function its passed to won't affect the "source" struct outside the function.如果我将一个结构作为参数传递给一个函数,我相信我是按值传递的,这意味着我实际上是在内存中创建一个新结构,并且在它传递给的函数内部对该结构的更改不会影响“源”结构在函数之外。 However, if I pass a pointer to a struct, there's still only one original struct, and changes to the struct referenced by the pointer will be visible to any code which is aware of this struct.但是,如果我将一个指针传递给一个结构,仍然只有一个原始结构,并且对指针引用的结构的更改将对任何知道该结构的代码可见。 Do I have that right?我有这个权利吗?

So, is there any difference with objects?那么,对象有什么区别吗? When I pass a non-pointer object to a function, does the entire object get copied?当我将一个非指针对象传递给一个函数时,是否会复制整个对象?

It's exactly as you said.跟你说的一模一样。

When you pass an object by value, its copy constructor is invoked to produce a new instance of such object that will be used inside the function.当您按值传递对象时,将调用其复制构造函数以生成将在函数内部使用的此类对象的新实例。 The changes done to such new object won't be reflected to the original one 1 .对此类新对象所做的更改不会反映到原始对象1

As with structures, the default copy constructor just does a shallow copy of the original object - ie, its fields are copied 2 to the new instance;与结构一样,默认复制构造函数只是对原始对象进行浅表复制——即,它的字段被复制2到新实例; in many cases this is not desirable (eg if the object wraps a pointer/another resource), so there are classes which redefine the copy constructor or disable it completely.在许多情况下,这是不可取的(例如,如果对象包装了一个指针/另一个资源),因此有些类会重新定义复制构造函数或完全禁用它。 Objects of these last classes can only be passed by pointer or reference.最后这些类的对象只能通过指针或引用传递。

Passing objects by value can be costly if they are bigger than a pointer (in size) or in general if their copy constructor isn't "cheap".如果对象大于指针(在大小上),或者通常如果它们的复制构造函数不“便宜”,则按值传递对象的成本可能很高。 On the other hand, in comparison to pointers, the pass-by-value yields the usual advantages of not having to specify the pointer ownership, letting the callee do whatever it wants with the object, etc.另一方面,与指针相比,按值传递具有不必指定指针所有权、让被调用者对对象做任何想做的事情等通常的优点。

Notice that passing an object by value kills the polymorphism.请注意,按值传递对象会破坏多态性。 This because a function receiving an object by value receives a statically typed object, with a precise size and type, so any attempt to pass an object of a derived class will result in object slicing (the copy constructor for the base class is called, that by default just copies the fields that are available in the base class).这是因为按值接收对象的函数接收静态类型对象,具有精确的大小和类型,因此任何传递派生类对象的尝试都将导致对象切片(调用基类的复制构造函数,即默认情况下只复制基类中可用的字段)。

This is the reason why often the preferred method of passing objects is by const reference.这就是为什么传递对象的首选方法通常是通过const引用的原因。 This yields several advantages:这产生了几个优点:

  • no copies involved;不涉及副本; the object that the callee will see will be exactly the one specified at the moment of the call;被调用者将看到的对象将与调用时指定的对象完全相同;
  • no changes to the original object can be made, thanks to the const qualifier;由于const限定符,不能对原始对象进行任何更改;
  • if however the callee needs to change a copy of the object, it can still construct a copy by itself from the reference;但是,如果被调用者需要更改对象的副本,它仍然可以根据引用自己构造一个副本;
  • no awkward pointer syntax;没有笨拙的指针语法;
  • polymorphism preserved, since behind the scenes we're actually passing a pointer;保留了多态性,因为在幕后我们实际上传递了一个指针;
  • no big doubts about object ownership: the general rule about references is that they are owned by the caller.对对象所有权毫无疑问:关于引用的一般规则是它们由调用者拥有。

  1. As far as the "raw fields" of the object are concerned;就对象的“原始字段”而言; naturally if the original object and the copy continue to share a pointer/handle to the same resource some modifications to one may affect the other.当然,如果原始对象和副本继续共享指向同一资源的指针/句柄,对其中一个的某些修改可能会影响另一个。

  2. Primitive types (and in general PODs) are copied bitwise, while the copy constructor is called for non-POD types.原始类型(和一般的 POD)按位复制,而复制构造函数被调用用于非 POD 类型。

The difference mostly has to do with where in memory an object is allocated.差异主要与对象在内存中的分配位置有关。 For instance:例如:

int main() {
    MyObject x;   //allocates space for an instance of MyObject on the stack
    MyObject* y;  //allocates space for a pointer on the stack
    MyObject* z = new MyObject();  //allocates space for a pointer on the 
                                   //stack and an object instance in the heap and
                                   //sets the pointer to point to the new instance
    MyObject* a = &x;  //allocates space for a pointer on the stack and 
                       //makes it point to 'x'
    ...
}

int someFunc(MyObject byValue, MyObject* byReference) {
   //the 'byValue' parameter will be passed by creating a copy of the 
   //entire source object on the stack (can be quite expensive for 
   //complex object types)

   //the 'byReference' parameter will be passed by creating a 
   //copy of the source pointer on the stack and setting it to 
   //point to the source object in memory
}

In C++, a variable is the variable that it is representing.在 C++ 中,变量它所代表的变量。 It is the actual object in memory, at the actual location.它是内存中的实际对象,位于实际位置。

However, you can choose to make such a variable represent a pointer instead, in which case it'll say "Hey, I'm me, I am pointing over there, The object you want isn't here. it's THERE, Yes, there. Go on, get there!".然而,你可以选择让这样一个变量代表一个指针,在这种情况下它会说“嘿,我是我,我指向那边,你想要的对象不在这里。它在那里,是的,那里。继续,到那儿!”。

Unless you're explicitly using C++'s "reference type", which I suspect you're not, then ALL arguments you pass are by value.除非您明确使用 C++ 的“引用类型”(我怀疑您不是),否则您传递的所有参数都是按值传递的。

The answers to the questions in your second and third paragraph are both "yes".第二段和第三段中问题的答案都是“是”。 More specifically, if you pass an object to a function by value, the function will receive a copy of that object (created by the copy constructor).更具体地说,如果您按值将对象传递给函数,该函数将收到该对象的副本(由复制构造函数创建)。

When you pass an object to a function by value, it's copied by means of its class's copy constructor.当您按值将对象传递给函数时,它会通过其类的复制构造函数进行复制。 If you haven't defined a copy constructor, there'll be a default one supplied by the compiler (unless you take special steps to avoid that), which is equivalent to copying the members by hand.如果您没有定义复制构造函数,编译器将提供一个默认的复制构造函数(除非您采取特殊步骤来避免这种情况),这相当于手动复制成员。

The preferred thing to do is often actually to pass a const reference rather than either a pointer or the object itself.首选的做法通常实际上是传递 const 引用,而不是指针或对象本身。

(You might want to be aware that actually a struct is just a class whose members are public by default; in particular, structs can have user-defined copy constructors too. A struct is not necessarily just plain inert data.) (您可能想知道,实际上struct只是一个默认情况下其成员是publicclass ;特别是,结构也可以具有用户定义的复制构造函数。结构不一定只是普通的惰性数据。)

You have that right.你有那个权利。

Indeed, that's how it works.确实,这就是它的工作原理。 A pointer stores the memory address of a variable.指针存储变量的内存地址。

When you pass a pointer (to an object) for a function as a parameter, it means that function will have access to that object through it's memory address instead of a new object being created on the stack.当您将一个指针(指向一个对象)作为参数传递给一个函数时,这意味着该函数将可以通过它的内存地址访问该对象,而不是在堆栈上创建一个新对象。

Check this thread for more info on pointers.检查此线程以获取有关指针的更多信息。

  • A pointer stores an memory address.指针存储内存地址。
  • A variable stores a value.变量存储一个值。

Ex:前任:

Player * a; // Allocated an int value to stored an address, you will able to access to value at that address by a -> but you have to allocated it and free when it done

Player a; // Allocated a block of memory that size equal = Player size.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM