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

时间:2011-03-21 00:38:22

标签: c++ pointers object

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

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

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

7 个答案:

答案 0 :(得分:15)

正如你所说。

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

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

如果值大于指针(大小),或者通常如果它们的复制构造函数不“便宜”,那么按值传递对象可能会很昂贵。另一方面,与指针相比,pass-by-value产生了通常的优点,即不必指定指针所有权,让被调用者对对象做任何想做的事情等。

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

这就是为什么传递对象的首选方法通常是const引用。这带来了几个好处:

  • 没有涉及副本;被调用者将看到的对象将是呼叫时指定的对象;
  • 由于const限定符;
  • ,无法对原始对象进行任何更改
  • 如果被调用者需要更改对象的副本,它仍然可以从引用中自行构建副本;
  • 没有笨拙的指针语法;
  • 保留了多态性,因为在幕后我们实际上传递了一个指针;
  • 对对象所有权没有太大疑问:关于引用的一般规则是它们归调用者所有。

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

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

答案 1 :(得分:3)

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

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
}

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

(您可能需要注意,实际上struct只是class,默认情况下其成员为public;特别是,结构也可以包含用户定义的副本构造函数。结构不一定只是普通的惰性数据。)

答案 5 :(得分:0)

你有这个权利。

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

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

检查this thread以获取有关指针的更多信息。

答案 6 :(得分:0)

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

例如:

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.