繁体   English   中英

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

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

在java和objective-c中,表示对象的变量一般是指向该对象的指针。 但是,在 C++ 中,非指针类型保存对象似乎很常见。 两者有什么区别?

如果我将一个结构作为参数传递给一个函数,我相信我是按值传递的,这意味着我实际上是在内存中创建一个新结构,并且在它传递给的函数内部对该结构的更改不会影响“源”结构在函数之外。 但是,如果我将一个指针传递给一个结构,仍然只有一个原始结构,并且对指针引用的结构的更改将对任何知道该结构的代码可见。 我有这个权利吗?

那么,对象有什么区别吗? 当我将一个非指针对象传递给一个函数时,是否会复制整个对象?

跟你说的一模一样。

当您按值传递对象时,将调用其复制构造函数以生成将在函数内部使用的此类对象的新实例。 对此类新对象所做的更改不会反映到原始对象1

与结构一样,默认复制构造函数只是对原始对象进行浅表复制——即,它的字段被复制2到新实例; 在许多情况下,这是不可取的(例如,如果对象包装了一个指针/另一个资源),因此有些类会重新定义复制构造函数或完全禁用它。 最后这些类的对象只能通过指针或引用传递。

如果对象大于指针(在大小上),或者通常如果它们的复制构造函数不“便宜”,则按值传递对象的成本可能很高。 另一方面,与指针相比,按值传递具有不必指定指针所有权、让被调用者对对象做任何想做的事情等通常的优点。

请注意,按值传递对象会破坏多态性。 这是因为按值接收对象的函数接收静态类型对象,具有精确的大小和类型,因此任何传递派生类对象的尝试都将导致对象切片(调用基类的复制构造函数,即默认情况下只复制基类中可用的字段)。

这就是为什么传递对象的首选方法通常是通过const引用的原因。 这产生了几个优点:

  • 不涉及副本; 被调用者将看到的对象将与调用时指定的对象完全相同;
  • 由于const限定符,不能对原始对象进行任何更改;
  • 但是,如果被调用者需要更改对象的副本,它仍然可以根据引用自己构造一个副本;
  • 没有笨拙的指针语法;
  • 保留了多态性,因为在幕后我们实际上传递了一个指针;
  • 对对象所有权毫无疑问:关于引用的一般规则是它们由调用者拥有。

  1. 就对象的“原始字段”而言; 当然,如果原始对象和副本继续共享指向同一资源的指针/句柄,对其中一个的某些修改可能会影响另一个。

  2. 原始类型(和一般的 POD)按位复制,而复制构造函数被调用用于非 POD 类型。

差异主要与对象在内存中的分配位置有关。 例如:

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
}

在 C++ 中,变量它所代表的变量。 它是内存中的实际对象,位于实际位置。

然而,你可以选择让这样一个变量代表一个指针,在这种情况下它会说“嘿,我是我,我指向那边,你想要的对象不在这里。它在那里,是的,那里。继续,到那儿!”。

除非您明确使用 C++ 的“引用类型”(我怀疑您不是),否则您传递的所有参数都是按值传递的。

第二段和第三段中问题的答案都是“是”。 更具体地说,如果您按值将对象传递给函数,该函数将收到该对象的副本(由复制构造函数创建)。

当您按值将对象传递给函数时,它会通过其类的复制构造函数进行复制。 如果您没有定义复制构造函数,编译器将提供一个默认的复制构造函数(除非您采取特殊步骤来避免这种情况),这相当于手动复制成员。

首选的做法通常实际上是传递 const 引用,而不是指针或对象本身。

(您可能想知道,实际上struct只是一个默认情况下其成员是publicclass ;特别是,结构也可以具有用户定义的复制构造函数。结构不一定只是普通的惰性数据。)

你有那个权利。

确实,这就是它的工作原理。 指针存储变量的内存地址。

当您将一个指针(指向一个对象)作为参数传递给一个函数时,这意味着该函数将可以通过它的内存地址访问该对象,而不是在堆栈上创建一个新对象。

检查此线程以获取有关指针的更多信息。

  • 指针存储内存地址。
  • 变量存储一个值。

前任:

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