Mentions légales du service

Skip to content
Snippets Groups Projects
Commit f9a76c94 authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

Reformulate the paragraph about ; at end of struct.

parent 61d261c1
Branches
Tags
No related merge requests found
%% Cell type:markdown id: tags:
# [Getting started in C++](./) - [Object programming](./0-main.ipynb) - [Introduction to the concept of object](./1-Introduction.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#Motivation" data-toc-modified-id="Motivation-1">Motivation</a></span></li><li><span><a href="#The-C-response:-the-struct" data-toc-modified-id="The-C-response:-the-struct-2">The C response: the <code>struct</code></a></span></li><li><span><a href="#Passing-a-struct-to-a-function" data-toc-modified-id="Passing-a-struct-to-a-function-3">Passing a struct to a function</a></span><ul class="toc-item"><li><span><a href="#Pass-by-const-reference" data-toc-modified-id="Pass-by-const-reference-3.1">Pass-by-const-reference</a></span></li><li><span><a href="#Pass-by-pointer" data-toc-modified-id="Pass-by-pointer-3.2">Pass-by-pointer</a></span></li></ul></li><li><span><a href="#Initialization-of-objects" data-toc-modified-id="Initialization-of-objects-4">Initialization of objects</a></span></li></ul></div>
%% Cell type:markdown id: tags:
## Motivation
%% Cell type:markdown id: tags:
Sometimes, there are variables that are bound to be initialized and used together. Let's consider the position of a point in a three-dimensional space:
%% Cell type:code id: tags:
``` C++17
#include <iostream>
#include <cmath> // For std::sqrt
double norm(double v_x, double v_y, double v_z)
{
return std::sqrt( v_x * v_x + v_y * v_y + v_z * v_z );
}
{
double v1_x, v1_y, v1_z;
v1_x = 1.;
v1_y = 5.;
v1_z = -2.;
std::cout << norm(v1_x, v1_y, v1_z) << std::endl;
double v2_x, v2_y, v2_z;
v2_x = 2.;
v2_y = 2.;
v2_z = 4.;
std::cout << norm(v2_x, v2_y, v2_z) << std::endl;
}
```
%% Cell type:markdown id: tags:
The code above is completely oblivious of the close relationship between `x`, `y` and `z`, and for instance the norm function takes three distinct arguments.
This is not just an inconveniency: this can lead to mistake if there is an error in the variables passed:
%% Cell type:code id: tags:
``` C++17
{
double v1_x, v1_y, v1_z;
v1_x = 1.;
v1_y = 5.;
v1_z = -2.;
double v2_x, v2_y, v2_z;
v2_x = 2.;
v2_y = 2.;
v2_z = 4.;
const double norm1 = norm(v1_x, v1_y, v2_z); // probably not what was intended, but the program
// has no way to figure out something is fishy!
}
```
%% Cell type:markdown id: tags:
## The C response: the `struct`
C introduced the `struct` to be able to group nicely data together and limit the risk I exposed above:
%% Cell type:code id: tags:
``` C++17
struct Vector
{
double x;
double y;
double z;
};
```
%% Cell type:code id: tags:
``` C++17
double norm(Vector v)
{
return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
{
Vector v1;
v1.x = 1.;
v1.y = 5.;
v1.z = -2.;
std::cout << norm(v1) << std::endl;
Vector v2;
v2.x = 2.;
v2.y = 2.;
v2.z = 4.;
std::cout << norm(v2) << std::endl;
}
```
%% Cell type:markdown id: tags:
Calling `norm` is now both more elegant (only one argument) and less dangerous (I can't mix by mistake coordinates from different objects).
Let's introduce at this point a bit of vocabulary:
- `x`, `y` and `z` in the structure are called **member variables** or **data attributes** (often shorten as **attributes** even if in a class this is actually not completely proper). On a side note: some C++ purists will be adamant only **member variables** should be used; but I rather use **data attributes** which is the term preferred in many others object programming languages.
- `Vector` is a **struct**, which is a somewhat simplified **class** (we will explain the difference when we'll introduce classes).
- `v1` and `v2` are **objects**.
Let's also highlight the `.` syntax which allows to access the attributes of an object (e.g `v1.x`).
%% Cell type:markdown id: tags:
### The semicolon at the end of a `struct`
This comes historically from the C, where a `struct` is considered as a type declaration and it allows to do:
**Xeus-cling issue:** Here cling doesn't manage to compile it but it is accepted rightfully by a full-fledged compiler (see for instance [@Coliru](http://coliru.stacked-crooked.com/a/3b77606ea8082485)):
This comes historically from the C, where a `struct` could be defined and initialized at the same time (or should - Xeus-cling doesn't manage it... As usual you may check a full-fledged compiler accepts it [@Coliru](http://coliru.stacked-crooked.com/a/3b77606ea8082485)):
%% Cell type:code id: tags:
``` C++17
// Xeus-cling issue (at least circa May 2021)
struct Vector
{
double x;
double y;
double z;
} v1; // Here the struct is declared and at the same time an object v1 is created
v1.x = 1.;
v1.y = 5.;
v1.z = -2.;
```
%% Cell type:markdown id: tags:
This is the reason why a semicolon is always required at the end of a `struct` or a `class` declaration.
This is absolutely **not** encouraged in C++, but it may help you to remember always closing a `struct` (or later a `class`) with a semicolon.
%% Cell type:markdown id: tags:
## Passing a struct to a function
In the `norm` function above, we passed as argument an object of `Vector` type by value. When we introduced functions, we saw there were three ways to pass an argument:
* By value.
* By reference.
* By pointers.
I didn't mention there the copy cost of a pass-by-value: copying a plain old data (POD) type such as an `int` or a `double` is actually cheap, and is recommended over a reference. But the story is not the same for an object: the cost of copying the object in the case of a pass-by-value may actually be quite high (imagine if there were an array with thousands of double values inside for instance) - and that's supposing the object is copyable (but we're not quite ready yet to deal with [that aspect](../3-Operators/4-CanonicalForm.ipynb#Uncopyable-class)).
### Pass-by-const-reference
So most of the time it is advised to pass arguments by reference, often along a `const` qualifier if the object is not to be modified by the function:
%% Cell type:code id: tags:
``` C++17
double norm_without_copy(const Vector& v)
{
return std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
{
Vector v1;
v1.x = 1.;
v1.y = 5.;
v1.z = -2.;
std::cout << norm_without_copy(v1) << std::endl;
}
```
%% Cell type:markdown id: tags:
### Pass-by-pointer
Of course, if for some reason you prefer to use pointers it is also possible:
%% Cell type:code id: tags:
``` C++17
double norm(const Vector* const v) // can keep the name here: no possible ambiguity
{
return std::sqrt((*v).x * (*v).x + (*v).y * (*v).y + (*v).z * (*v).z);
}
{
Vector v1;
v1.x = 1.;
v1.y = 5.;
v1.z = -2.;
std::cout << norm(&v1) << std::endl;
}
```
%% Cell type:markdown id: tags:
This is more than little verbosy, so a shortcut has been introduced; `->` means you dereference a pointer and then calls the attribute:
%% Cell type:code id: tags:
``` C++17
double norm_with_pointer_shortcut(const Vector* const v)
{
return std::sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
}
{
Vector v1;
v1.x = 1.;
v1.y = 5.;
v1.z = -2.;
std::cout << norm_with_pointer_shortcut(&v1) << std::endl;
}
```
%% Cell type:markdown id: tags:
## Initialization of objects
So far, we have improved the way the `norm` function is called, but the initialization of a vector is still a bit tedious. Let's wrap up a function to ease that:
%% Cell type:code id: tags:
``` C++17
void init(Vector& v, double x, double y, double z)
{
v.x = x;
v.y = y;
v.z = z;
}
```
%% Cell type:code id: tags:
``` C++17
{
Vector v1;
init(v1, 1., 5., -2.);
std::cout << "Norm = " << norm(v1) << std::endl;
}
```
%% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018-2021_
_This notebook is an adaptation of a lecture prepared by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been written by Sébastien Gilles and Vincent Rouvreau (Inria)_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment