简体   繁体   English

创建C ++对象

[英]Creating C++ objects

I noticed that there are two ways to create C++ objects: 我注意到有两种方法可以创建C ++对象:

BTree *btree = new BTree;

and

BTree btree;

From what I can tell, the only difference is in how class objects are accessed (. vs. -> operator), and when the first way is used, private integers get initialized to 0. 据我所知,唯一的区别在于如何访问类对象(。与 - >运算符),并且当使用第一种方式时,私有整数被初始化为0。

Which way is better, and what's the difference? 哪种方式更好,有什么区别?

How do you know when to use one or the other? 你怎么知道何时使用其中一个?

Two differences: 两个区别:

  • they create the objects in different parts of the memory (heap vs stack) 他们在内存的不同部分创建对象(堆与堆栈)

  • the object lifetime is different: In the first case, the code manages the memory allocation explicitly, and it must also manage the deallocation explicitly (using delete/delete[]). 对象生存期是不同的:在第一种情况下,代码显式地管理内存分配, 它还必须显式地管理释放 (使用delete / delete [])。

    In the second case, the object is automatically deallocated at the end of its enclosing scope (either a method, a nested block within a method, or a class) 在第二种情况下,对象在其封闭范围的末尾自动释放(方法,方法中的嵌套块或类)

Which one you uses depends mostly on the lifetime of the object (if it should outlive the method in which it is created or not). 您使用哪一个主要取决于对象的生命周期(如果它应该比创建它的方法更长)。

The first form creates the object on the heap whereas the second creates it on the stack. 第一个表单在堆上创建对象,而第二个表单在堆栈上创建它。

The second from will be destroyed when the function is finished running. 当函数完成运行时,第二个将被销毁。 The first will remain alive until specifically deleted. 第一个将保持活着,直到被特别删除。

The second form is best if you want to only use the object in the current scope. 如果您只想使用当前范围中的对象,则第二种形式最好。 You don't need to worry about getting rid of it because it'll be done for you. 你不必担心摆脱它,因为它会为你完成。 Also note that some libraries don't work if there classes are created on the stack. 另请注意,如果在堆栈上创建了类,则某些库不起作用。

If the object should outlive the function, the new form is a better option. 如果对象应该比该函数寿命更长,则新表单是更好的选择。

Another difference between these two form is the time when storage for those objects are allocated. 这两种形式之间的另一个区别是分配这些对象的存储时间。 The form BTree bTree; 形式BTree bTree; names static allocation whose allocation accomplishes at compile time -- ie the compiler will arrange memory space for this object in memory when running. 命名静态分配,其分配在编译时完成 - 即编译器在运行时将在内存中为此对象安排内存空间。 While, the allocation for BTree *pbTree = new BTree , the alleged dynamic allocation -- performs at runtime -- ie the momory will be allocated only when the running program reach this point. BTree *pbTree = new BTreeBTree *pbTree = new BTree的分配,所谓的动态分配 - 在运行时执行 - 即仅在正在运行的程序到达此点时才分配。

In this situation, the difference between static and dynamic allocation is not apparent. 在这种情况下,静态和动态分配之间的差异并不明显。 Consider the following circumstance where you need to allocate memory space for an integer array, but number of elements can be determined only at runtime, ie we can only know the exact memory space consumed by the array after the program begin to execute. 考虑以下情况,您需要为整数数组分配内存空间,但元素数量只能在运行时确定,即我们只能知道程序开始执行后数组所消耗的确切内存空间。

// in this function, we want to return a copy of the parameter array
int *array_cpy( int *arr, int num ){
    int *copy = new int[ num ];

    int i;
    for( i = 0; i < num; i++ ){
        copy[ i ] = arr[ i ];
    }

    return copy;
}

Here the definition int copy[ num ]; 这里定义int copy[ num ]; is not appropriate, one reason is for what I have stated above, the other is the lifetime of copy outlive the function. 是不合适的,一个原因是我上面所说的,另一个是copy寿命的功能。 However, given VLA is permitted in recent language specification, the second reason is key to this problem. 但是,鉴于最近的语言规范允许VLA,第二个原因是这个问题的关键。

In choosing between whether you should stack or heap allocate memory, you need to dig a little into the differences between the two. 在选择是否应该堆栈或堆分配内存时,您需要深入研究两者之间的差异。

Yes, stack memory has the advantage of being deallocated automatically when it goes out of scope, although the same can be achieved with smart pointers and heap allocation. 是的,堆栈内存具有在超出范围时自动解除分配的优点,尽管使用智能指针和堆分配可以实现相同的目的。 More important are the reasons behind why this happens. 更重要的是发生这种情况的原因。

Performance: Stack memory is cleaned up automatically because it involves the simply shift of a stack pointer when the memory goes out of scope. 性能:堆栈内存自动清理,因为它涉及在内存超出范围时简单地移动堆栈指针。 For this reason, allocation and deallocation of stack memory is much faster than heap memory. 因此,堆栈内存的分配和释放比堆内存快得多。

Memory Lifetime: Heap allocated memory is available beyond the scope of the allocating function. 内存生存期:堆分配的内存超出了分配功能的范围。 Stack is not. 堆栈不是。 Following from the reasoning around adjustment of the stack pointer above, once memory is deallocated, it is free and very likely to be overwritten for the next stack allocation. 在围绕上面的堆栈指针调整的推理之后,一旦释放了存储器,它就是空闲的并且很可能被覆盖以用于下一个堆栈分配。

In short, use stack memory when the allocation is temporary, particularly if you need to allocate repeatedly and performance is important. 简而言之,当分配是临时的时,使用堆栈内存,特别是如果您需要重复分配并且性能很重要。 Use heap memory when the object needs to exist beyond the allocating method. 当对象需要存在于分配方法之外时,请使用堆内存。

The high-level distinction is object lifetime . 高级别的区别是对象的生命周期 For example, if you were writing a video game, you would allocate the objects corresponding to monsters on the heap, via new . 例如,如果您正在编写视频游戏,则可以通过new分配堆上怪物对应的对象。 That way, the monster's underlying object lives exactly as long as the monster does, which is unknowable when you write the program. 这样,怪物的底层物体就像怪物一样长寿,这在编写程序时是不可知的。 When the player kills the monster, your code can destroy the monster object using delete . 当玩家杀死怪物时,你的代码可以使用delete来摧毁怪物对象。

A total-score counter, on the other hand, you would use the other form, because you know how long you want the counter to stay around (presumably, as long as the game is running!). 总分计数器,另一方面,你会使用另一种形式,因为你知道你希望计数器停留多长时间(大概是,只要游戏正在运行!)。 By putting that form in the "global scope," outside of any function body, it would be allocated statically, as part of the program binary itself. 通过将该表单放在任何函数体之外的“全局作用域”中,它将作为程序二进制文件本身的一部分静态分配。

Finally, if you were computing the sum of an array, like this: 最后,如果你计算数组的总和,就像这样:

int mysum(int* arr, int len) {
  int sum = 0;
  for (int i = 0; i < len; ++i) { sum += arr[i] }
  return sum;
}

the sum variable is allocated on the stack, which is basically what you want: a temporary variable that you don't have to explicitly deallocate, and which is only around when that function is actually running. sum变量是在堆栈上分配的,这基本上是你想要的:一个临时变量,你不必显式解除分配,而只是在该函数实际运行时。

Well, they're being stored in quite different regions of memory. 好吧,它们被存储在完全不同的内存区域。

Here's a good read. 这是一个很好的阅读。 Heap and Stack 堆和堆栈

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

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