问题
When is it advantageous to use Record
type vs a Class in Chapel? On IRC someone mentioned that Records distribute over locales better or something.
回答1:
Records and classes are similar in Chapel in that they both support the creation of objects with fields and methods. That said, there are some major differences as well . Here's a quick review of some of those differences (tl;dr: records are roughly like C structs while classes support class hierarchies, dynamic dispatch, etc.), followed by a summary that gives some indications as to when you might choose to use one or the other:
Nature of Variables
- record variables represent a record object directly
- class variables represent a reference (pointer) to a class object
Put another way, a record variable is the record object, such that there is no distinguishing between the two. In contrast, a class variable points to a class object which may be stored on a different locale from the variable itself (i.e., class variables can refer to objects stored across distributed memories).
An implication of this is that when one record is assigned to another, the value of the RHS record is copied to the LHS record's value (e.g., typically the fields of the RHS record are copied to the fields of the LHS record). Another implication is that records have to define (or use the compiler-provided) copy initializers, and often provide 0-argument initializers to establish new record objects.
In contrast, when one class is assigned to another it makes the LHS class variable refer (point) to the same object as the RHS class variable.
Allocation/Deallocation
- class objects are allocated on the heap and can be governed by various memory management policies
- record objects are allocated "in place" (e.g., on the current stack frame) and are automatically de-allocated (e.g., when they go out of scope)
This means that the lifetime of a class object can be independent of the program's structure, where it relies on one of several policies to manage its memory (owned
, shared
, borrowed
, unmanaged
). In contrast, record objects can be thought of as always being automatically memory managed, yet constrained by lexical scoping.
As a specific example, if you have an array of classes, you've typically created a contiguous sequence of pointers that may refer to objects living anywhere on the system (the local heap or some other locale's heap). Whereas if you have an array of records, its storage will typically be a contiguous sequence of record objects.
An implication of this is that if you want to create a "pointer-based" data structure in Chapel—like a linked list, tree, or graph—you will typically use class objects to store the nodes of that data structure with fields of class type to refer to their neighbors (whereas it would be challenging to represent these nodes using records since Chapel has no pointers and they're allocated in-place).
Inheritance / Method Dispatch
- a class can be declared as a subclass of another class, supporting virtual methods / dynamic dispatch
- records do not support object hierarchies nor virtual/dynamic dispatch
This means that if you want to create an object hierarchy as in Java or C++, you'll want to use classes, and that initializers for such class hierarchies are themselves hierarchical.
Summary
Given these distinctions, you'll typically want to use a class if:
- you want to create a "pointer-based" data structure (e.g., a linked list) because class types can refer to themselves / one another using class variable fields
- you want to create object hierarchies supporting dynamic method dispatch
- you want to work with objects that are not constrained by their lexical scope
- you want to work with objects whose identity matters
You'll typically want to use a record if:
- value matters more than identity and it's OK to copy that value around
- you want object memory to be managed by the variable's scope
- you want more control over how objects are laid out in memory
In practice, combining the two can be quite powerful. For example, a record with a class field can be used to create a reference-counted object by having the class implement the object's identity and the record implement the reference counting semantics via assignment overloads and copy initializers to deal with the cases when copies of the record enter and leave scope, are assigned, etc.
来源:https://stackoverflow.com/questions/48331007/when-should-i-use-a-record-vs-a-class-in-chapel