C++ beginner(2)- variable and function

initialization

int x{}; // x is filled with zeroes, so x == 0
int x{123};
int x(123);
int a, b = 123, c{}, d{456}, e(789);
int* x, y, z; == int* x; int y; int z;
int *x, y, *z

Reference

C++ has two kinds of references: “lvalue” and “rvalue.” Just like with pointers, these are an annotation on another type:
we must initialize lvalue references and rvalue references when they are declared.

int a = 1;
// lvalue references
int& x = a;
int & x = a;
int &x =a;
 
// rvalue references
int&& x=a;
int && x=a;
int &&x=a;

Declaration and Definition

C++ have both a declaration and a definition

int Add(int a, int b);
int Add(int a, int b)
{
    return a + b;
}
// it’s possible to declare more than one function in a statement
int Add(int a, int b), Sub(int a, int b);
// arguments are optional! This declaration is totally fine
int Add(int, int);

Automatic Return Types

//C++ variables can be declared with an auto type, similar to var in C#. In C++, function return types can also be declared as auto
auto Add(int a, int b)
{
    return a + b;
}
// We can also specify the return type after the argument list if we put auto before the function name
auto Add(int a, int b) -> int
{
    return a + b;
}

Variadic Functions

it’s often considered a bad practice to even use the feature

// The `...` comes after all the normal arguments
// It means "0 or more arguments of any types go here"
void PrintLog(LogLevel level, ...)
{
    // ...
}

The function should then call va_start, va_arg, and va_end in order to get the arguments. This is quite type-unsafe and a very clunky interface, which is part of why the feature should generally not be used. There are several alternatives that are preferred instead, for example, overloading

Ref, Out, and In Arguments

Ref, Out, and In don’t exist in C++ . Instead, we use some conventions:

// Alternative to `ref`
// Use an lvalue reference, which is like a non-nullable pointer
void MovePlayer(Player& player, Vector3 offset)
{
    player.position += offset;
}
 
// Alternative to `in`
// Use a constant lvalue reference
// `const` means it can't be changed
void PrintPlayerName(const Player& player)
{
    DebugLog(player.name);
}
 
// Alternative to `out`
// Just use return values
ReallyBigMatrix ComputeMatrix()
{
    ReallyBigMatrix matrix;
    // ...math goes here...
    return matrix
}
 
// Another alternative to `out`
// Use lvalue reference arguments
void ComputeMatrix(ReallyBigMatrix& mat1, ReallyBigMatrix& mat2)
{
    mat1 = /* math for mat1 */;
    mat2 = /* math for mat2 */;
}
 
// Another alternative to `out`
// Pack the outputs into a return value
tuple<ReallyBigMatrix, ReallyBigMatrix> ComputeMatrix()
{
    return make_tuple(/* math for mat1 */, /* math for mat2 */);
}

Static Variables

Local variables within functions may be declared static. Similar to static fields of classes and structs in C#, this means that the variable has only one instance. A static C++ local variable has only one instance across all calls to the function:

Constexpr

Functions may be marked with constexpr. This means that the function can be evaluated at compile time. For example:

constexpr int GetSquareOfSumUpTo(int n)
{
    int sum = 0;
    for (int i = 0; i < n; ++i)
    {
        sum += i;
    }
    return sum * sum;
}

This function can then be evaluated at compile time in order to generate a constant:

DebugLog(GetSquareOfSumUpTo(5000));
 
// equivalent to...
 
DebugLog(1020530960);

The function can also be evaluated at runtime, such as when its parameters are dependent on runtime values:

int n = file.ReadInt();
DebugLog(GetSquareOfSumUpTo(n));
posted @ 2022-08-17 00:02  FrancisForeverhappy  阅读(24)  评论(0编辑  收藏  举报