[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/chenjisen/cppfront/main/docs/cpp2/objects.md [Back]  [Original]

## Overview

An object can be declared at any scope: in a namespace, in a `type`, in a function, in an expression.

Its declaration is written using the same **name `:` kind `=` value** [declaration syntax](../cpp2/declarations.md) as everything in Cpp2:

- **name** starts with a letter and is followed by other letters, digits, or `_`. Examples: `count`, `skat_game`, `Point2D` are valid names.

- **kind** is the object's type. In most places, except type scopes, you can write the `_` wildcard as the type (or omit the type entirely) to ask for the type to be deduced. When the type is a template, the templated arguments can be inferred from the constructor (via [CTAD](../welcome/hello-world.md#ctad)).

- **value** is the object's initial value. To use the default-constructed value, write `()`.


For example:

``` cpp title="Declaring some objects" hl_lines="3 4 7-9 12 13"
//  numbers is an object of type std::vector,
//  defined as having the initial contents 1, 2, 3
numbers: std::vector = (1, 2, 3);
numbers: std::vector = (1, 2, 3);       // same, deducing the vector's type

//  count is an object of type int, defined as having initial value -1
count: int = -1;
count: _ = -1;      // same, deducing the object's type with the _ wildcard
count := -1;        // same, deducing the object's type by just omitting it

//  pi is a variable template; == signifies the value never changes (constexpr)
pi:  T == 3.14159'26535'89793'23846L;
pi: _ == 3.14159'26535'89793'23846L;    // same, deducing the object's type
```

The object type can be deduced by writing `_` (the default, so it can be omitted). You can use `is` to declare a type constraint (e.g., a concept) that a deduced type must match, in which case `_` is required. For example:

``` cpp title="Declaring an object of constrained deduced type" hl_lines="2"
//  number's type is deduced, but must match the std::regular concept
number: _ is std::regular = some_factory_function();
```


##  Guaranteed initialization

Every object must be initialized using `=` before it is used.

An object in any scope can be initialized at its declaration. For example:

``` cpp title="Initializing objects when they are declared" hl_lines="4 10"
shape: type = {
    //  An object at type scope (data member)
    //  initialized with its type's default value
    points: std::vector = ();

    draw: (this, where: canvas) -> bool
    = {
        //  An object at function scope (local variable)
        //  initialized with color::red
        pen := color::red;

        // ...
    }

    //  ...
}
```

Additionally, at function local scope an object `obj` can be initialized separately from its declaration. This can be useful when the object must be declared before a program-meaningful initial value is known (to avoid a dead write of a wrong 'dummy' value), and/or when the object may be initialized in more than one way depending on other logic (e.g., by using different constructors on different paths). The way to do this is:

- Declare `obj` without an `= initializer` value, for example: `obj: some_type;`. This allocates stack space for the object, but does not construct it.

- `obj` must have a definite first use on every `#!cpp if`/`#!cpp else` branch path (and that first use must not be inside any loop), and

- that definite first use must be of the form `obj = value;` which is a constructor call, or else pass `obj` as an `out` argument to an `out` parameter (which is also effectively a constructor call, and performs the construction in the callee).

For example:

``` cpp title="Initializing local objects after they are declared" hl_lines="5 14 17 21"
f: () = {
    buf: std::array;   // uninitialized
    //  ... calculate some things ...
    //  ...  no uses of buf here  ...
    buf = some_calculated_value;        // constructs (not assigns) buf
    //  ...
    std::cout 

Web Proxy Viewer  |  New URL  |  Original Page