This commit is contained in:
Frank B. Brokken 2016-11-08 21:54:15 +01:00
parent 963ecb3b57
commit 75d04f6683
38 changed files with 85 additions and 87 deletions

View file

@ -36,13 +36,12 @@ data, are available to both modifiable and constant objects (cf. section
ref(ConstFunctions)).
To prevent emi(backdoors) we must also make sure that the data member is
not modifiable through an accessor's return value. For values of
built-in primitive types that's easy, as they are usually returned by value,
which are copies of the values found in variables.
But since objects may be fairly large making copies are usually prevented by
returning objects by reference. A backdoor is created by returning a data
member by reference, as in the following example, showing the allowed abuse
below the function definition:
not modifiable through an accessor's return value. For values of built-in
primitive types that's easy, as they are usually returned by value, which are
copies of the values found in variables. But since objects may be fairly
large making copies is usually prevented by returning objects by reference. A
backdoor is created by returning a data member by reference, as in the
following example, showing the allowed abuse below the function definition:
verb(
string &Person::name() const
{

View file

@ -6,12 +6,12 @@ return memory allocated by an object to the common pool when an object goes
destructors are therefore be discussed in depth in that chapter. In this
chapter the emphasis is on the class's organization and its constructors.
Constructor are recognized by their names which is equal to the class name.
Constructors do not specify return values, not even tt(void). E.g., the class
tt(Person) may define a constructor tt(Person::Person()). The bf(C++) run-time
system ensures that the constructor of a class is called when a variable of
the class is defined. It is possible to define a class lacking any
constructor. In that case the compiler defines a
Constructors are recognized by their names which are equal to their class
names. Constructors do not specify return values, not even tt(void). E.g.,
the class tt(Person) may define a constructor tt(Person::Person()). The
bf(C++) run-time system ensures that the constructor of a class is called when
a variable of the class is defined. It is possible to define a class lacking
any constructor. In that case the compiler defines a
hi(constructor: default) default constructor that is called when an object of
that class is defined. What actually happens in that case depends on the data
members that are defined by that class (cf. section ref(MemberInitializers)).

View file

@ -18,19 +18,18 @@ provided file name. Instead of repeating the initialization code in each
constructor, the common code can be factorized into a member tt(init) which
is called by the constructors.
Currently, bf(C++) offers an alternative by allowing
constructors to call each other. This is called
bf(C++) offers an alternative by allowing constructors to call each
other. This is called
hi(constructor: delegation)
emi(delegating constructors)
The C++11 standard
allows us to delegate constructors as illustrated by the next example:
which is illustrated by the next example:
verb(
class Stat
{
public:
Stat()
:
State("", "") // no filename/searchpath
Stat("", "") // no filename/searchpath
{}
Stat(std::string const &fileName)
:

View file

@ -44,7 +44,7 @@ in the return statement of functions. Examples:
Object definitions may be encountered in unexpected places, easily resulting in
(human) confusion. Consider a function `tt(func)' and a very simple
class tt(Fun) (tt(struct) is used, as data hiding is not an issue here;
in-class implementatinos are used for brevity):
in-class implementations are used for brevity):
verb(
void func();

View file

@ -18,9 +18,9 @@ ordinary functions.
However, as explained in chapter ref(POLYMORPHISM), when using polymorphism
the compiler must ignore the tt(inline) keyword and define so-called
em(virtual members) as true (em(out-of-line)
em(virtual members) as true (em(out-of-line))
hi(out-of-line functions)
functions). In this situation the vague linkage may cause problems, as the
functions. In this situation the vague linkage may cause problems, as the
compiler must decide in what object file(s) to put their code. Usually that's
not a big problem as long as the function is at least called once. But virtual
functions are special in the sense that they may very well never be explicitly

View file

@ -37,7 +37,7 @@ The constructors merely have to call these tt(copy) members:
)
Interestingly, no `initialization followed by assignment' happens here:
tt(d_union) has not been initialized in any way by the the time we reach the
tt(d_union) has not been initialized in any way by the time we reach the
statement blocks of the above constructors. But upon reaching the statement
blocks, tt(d_union) memory is merely raw memory. This is no problem, as the
tt(copy) members use placement new to initialize the tt(Union)'s memory:

View file

@ -60,7 +60,7 @@ supplied variables.
it() The emi(extraction operator) (rshift()) performs a so called
emi(type safe) assignment to a variable by `extracting' its value from
a text stream. Normally, the extraction operator skips all
emi(white space) hi(skipping leading blanks) characters preceding
emi(whitespace) hi(skipping leading blanks) characters preceding
the values to be extracted.
it() Special i(symbolic constants) are used for special
situations. Normally a line is terminated by inserting tt("\n") or

View file

@ -140,7 +140,7 @@ should be ignored):
At (1) tt(d2) appropriately receives a copy of tt(d1)'s text. But at (2)
tt(d3) receives a copy of the text stored in the temporary returned by the
tt(dataFactory) function. As the temporary ceases to exist after the call to
tt(copy()) two releated and unpleasant consequences are observed:
tt(copy()) two related and unpleasant consequences are observed:
itemization(
it() The return value is a temporary object: its only reason for
existence is to pass its data on to tt(d3). Now tt(d3) copies the

View file

@ -1,9 +1,9 @@
To improve the readability of large numbers
em(digit separators)hi(digit separator) for integer and floating point
literals. The digit separator is a single quote which may be inserted between
digits of such literals to enhance human readability. Multiple digit
separators may be used, but only one separator can be inserted between
successive digits. E.g.,
literals can be used. The digit separator is a single quote which may be
inserted between digits of such literals to enhance human
readability. Multiple digit separators may be used, but only one separator can
be inserted between successive digits. E.g.,
verb(
1'000'000
3.141'592'653'589'793'238'5

View file

@ -62,7 +62,7 @@ used to convert a tt(void *) to an intended destination pointer. This is a
somewhat awkward left-over from bf(C), which should probably only be used in
that context. Here is an example:
The tt(qsort) functions from the bf(C) library expects a pointer to a
The tt(qsort) function from the bf(C) library expects a pointer to a
(comparison) function having two tt(void const *) parameters. In fact, these
parameters point to data elements of the array to be sorted, and so the
comparison function must cast the tt(void const *) parameters to pointers to

View file

@ -203,7 +203,7 @@ cout << 16.0 << ", " << 16.1;
)
)
bf(Handling white space and flushing streams)
bf(Handling whitespace and flushing streams)
itemization(
ithtq(endl)(std::endl)
@ -234,9 +234,9 @@ cout << "hello" << flush; // avoid if possible.
)
)
ithtq(skipws)(ios::skipws)
(leading i(white space) characters (blanks, tabs, newlines, etc.) are
(leading i(whitespace) characters (blanks, tabs, newlines, etc.) are
skipped when a value is extracted from a stream. This is the default. If the
flag is not set, leading white space characters are not skipped.
flag is not set, leading whitespace characters are not skipped.
Manipulator: tt(std::skipws). Example:
verb(
cin.setf(ios::skipws); // to unset, use
@ -264,13 +264,13 @@ cout.write("xyz", 3); // flush follows write.
)
)
ithtq(ws)(std::ws)
(manipulator removing all i(white space) characters
(manipulator removing all i(whitespace) characters
(blanks, tabs, newlines, etc.) at the current file position. White space are
removed if present even if the flag tt(ios::noskipws) has been set.
Example (assume the input contains 4 blank characters followed by the
character tt(X)):
verb(
cin >> ws; // skip white space
cin >> ws; // skip whitespace
cin.get(); // returns 'X'
)
)

View file

@ -11,7 +11,6 @@ specialties. In the upcoming sections the following classes are discussed:
it() The class tt(istream), offering the basic facilities for doing input;
it() The class ti(ifstream), allowing us to read files
(comparable to bf(C)'s hi(fopen) tt(fopen(filename, "r")));
it() The class ti(istringstream), allowing us to read information from
text that is not stored on files (streams) but in memory (comparable to
bf(C)'s ti(sscanf) function).
it() The class ti(istringstream), allowing us to extract information from
memory rather than from file (comparable to bf(C)'s ti(sscanf) function).
)

View file

@ -25,8 +25,8 @@ rshift() available for the extraction of an tt(int), of a tt(double), of a
string, of an array of characters, possibly to a pointer, etc. etc.. String or
character array extraction
hi(string extraction) hi(extracting strings)
by default first skips all white space characters, and then extracts
all consecutive non-white space characters. Once an extraction operator has
by default first skips all whitespace characters, and then extracts
all consecutive non-whitespace characters. Once an extraction operator has
been processed the tt(istream) object from which the information was extracted
is returned and it can immediately be used for additional tt(istream)
operations that appear in the same expression.
@ -54,7 +54,7 @@ endOfFile() is returned if no more character are available.)
(the next single character read from the input stream is
stored in tt(ch). The member function returns the stream itself which may be
inspected to determine whether a character was obtained or not.)
ittq(istream& get(char *buffer, int len, char delim = '\n'))
ittq(istream &get(char *buffer, int len, char delim = '\n'))
(At most tt(len - 1) characters are read from the input
stream into the array starting at tt(buffer), which should be at least tt(len)
bytes long. Reading also stops when the delimiter tt(delim) is
@ -70,7 +70,7 @@ It is OK to specifiy an 0-valued character delimiter: this way NTB strings
may be read from a (binary) file.
)
ithtq(getline)
(istream& getline(char *buffer, int len, char delim = '\n'))
(istream &getline(char *buffer, int len, char delim = '\n'))
(this member function operates analogously to the tt(get) member
function, but tt(getline) removes tt(delim) from the stream if it is actually
encountered. The delimiter itself, if encountered, is em(not) stored in the
@ -81,18 +81,18 @@ tt(std::getline) which is generally preferred over this tt(getline) member
function that is described here (see section ref(STRINGMEMBERS)).
)
ithtq(ignore)
(istream& ignore())
(istream &ignore())
(one character is skipped from the input stream.)
ittq(istream& ignore(int n))
ittq(istream &ignore(int n))
(tt(n) characters are skipped from the input stream.)
ittq(istream& ignore(int n, int delim))
ittq(istream &ignore(int n, int delim))
(at most tt(n) characters are skipped but skipping characters
stops after having removed tt(delim) from the input stream.)
ithtq(peek)(int peek())
(this function returns the next available input character,
but does not actually remove the character from the input stream. endOfFile()
is returned if no more characters are available.)
ithtq(putback)(istream& putback(char ch))
ithtq(putback)(istream &putback(char ch))
(The character tt(ch) is `pushed back' into the input stream, to
be read again as the next available character. endOfFile() is returned if this
is not allowed. Normally, it is OK to put back one character. Example:
@ -112,7 +112,7 @@ when reading em(binary) files. Section ref(IFSTREAM) contains an example in
which this member function is used. The member function tt(gcount()) may be
used to determine the number of characters that were retrieved by tt(read).
)
ithtq(readsome)(istream& readsome(char *buffer, int len))
ithtq(readsome)(istream &readsome(char *buffer, int len))
(at most tt(len) bytes are read from the input stream into the
buffer. All available characters are read into the buffer, but if endOfFile()
is encountered, fewer bytes are read, without setting the tt(ios::eofbit)

View file

@ -28,7 +28,7 @@ stream (as returned by tt(tellp)).
)
ithtq(end)(ios::end)
(the stepsize is interpreted relative to the current end position
of the the stream.)
of the stream.)
)
It is OK to hi(seek beyond file boundaries) seek beyond the last file
position. Seeking before tt(ios::beg) raises the hi(failbit)tt(ios::failbit)

View file

@ -10,9 +10,9 @@ the following constructors and members:
(istringstream istr(string const &init,
ios::openmode mode = ios::in))
(the object is initialized with tt(init)'s contents)
itt(istringstream istr(ios::openmode mode = ios::in))
(this constructor is usually used as the default
constructor. Example:
ittq(istringstream istr(ios::openmode mode = ios::in))
(this constructor is usually used as the default
constructor. Example:
verb(
std::istringstream in;
)

View file

@ -20,7 +20,7 @@ designed for stream classes. Here is an example:
other = std::move(base); // moving streams is OK
// other = base; // this would ail: copy assignment
// other = base; // this would fail: copy assignment
// is not available for streams
}
)

View file

@ -43,7 +43,7 @@ em(vice versa)). The tt(istream) and tt(ostream) parts of tt(fstream) objects
share the stream's data buffer and by performing the seek operation the stream
either activates its tt(istream) or its tt(ostream) part. If the seek is
omitted, reading after writing and writing after reading simply fails. The
example shows a white space delimited word being read from a file, writing
example shows a whitespace-delimited word being read from a file, writing
another string to the file, just beyond the point where the just read word
terminated. Finally yet another string is read which is found just beyond the
location where the just written strings ended:

View file

@ -13,7 +13,7 @@ ti(bash) shell, this can be realized as follows:
program 2>/tmp/error.log
)
Following this command any error messages written by tt(program) are
saved on the file tt(/tmp/error.log), instead of appearing on the screen.
written to tt(/tmp/error.log), instead of appearing on the screen.
Here is an example showing how this can be implemented using tt(streambuf)
objects. Assume tt(program) expects an argument defining the name
@ -26,7 +26,7 @@ program's source text:
verbinclude(-a examples/redirection.cc)
itemization(
it() At lines 1-2 local variables are defined: tt(errlog) is the
tt(ofstream) to write the error messages too, and tt(cerr_buffer) is a pointer
tt(ofstream) to write the error messages to, and tt(cerr_buffer) is a pointer
to a tt(streambuf), to point to the original tt(cerr) buffer.
it() At line 3 the alternate error stream is opened.
it() At line 4 redirection takes place: tt(cerr) now writes to

View file

@ -1,7 +1,7 @@
#include <string>
using namespace std;
string *enlarge(string *old, unsigned oldsize, unsigned newsize)
string *enlarge(string *old, size_t oldsize, size_t newsize)
{
string *tmp = new string[newsize]; // allocate larger array

View file

@ -10,7 +10,7 @@ are can be implemented.
In this fast-swap method we merely swap the contents of the tt(sizeof(Class))
bytes. This procedure may be applied to classes whose objects may be swapped
using a member-by-member swapping operation and can (in practice, although
this probabaly overstretches the allowed operations as described by the
this probably overstretches the allowed operations as described by the
bf(C++) ANSI/ISO standard) also be used in classes having reference data
members. It simply defines a buffer of tt(sizeof(Class)) bytes and performs a
circular ti(memcpy) operation. Here is its implementation for a hypothetical

View file

@ -75,7 +75,7 @@ realized in the overloaded assignment operator. An object's dynamically
allocated memory is em(duplicated), so that it contains its own allocated
data. The copy constructor is simpler than the overloaded assignment operator
in that it doesn't have to delete previously allocated memory. Since the
object is going to be created no previously allocated memory already exists.
object is going to be created no memory has already been allocated.
tt(Strings)'s copy constructor can be implemented as follows:
verb(

View file

@ -25,7 +25,7 @@ incorrect:
d_address(tmp.d_address)
{}
)
It is incorrect as it tt(string)'s copy constructors rather than
It is incorrect as tt(string)'s copy constructors rather than
tt(string)'s move constructors are called. If you're wondering why this
happens then remember that move operations are em(only) performed for
anonymous objects. To the compiler anything having a name isn't anonymous. And
@ -52,7 +52,7 @@ ti(utility).
When a class using composition not only contains class type data members
but also other types of data (pointers, references, primitive data types),
then these other data types can be initialized as usual. Primitive data type
members can simply be copied; references can be initialized as usual en
members can simply be copied; references can be initialized as usual and
pointers may use move operations as discussed in the previous section.
The compiler never calls move operations for variables having names. Let's

View file

@ -22,11 +22,11 @@ determined by the type of the pointer whether a pointer to dynamically
allocated memory points to a single entity or to an array of entities.
What happens if tt(delete) rather than tt(delete[]) is used? Consider the
following situation, in which the destructor tt(~Strings) is modified so
that it tells us that it is called. In a tt(main) function an array of two
tt(Strings) objects is allocated by tt(new), to be deleted by tt(delete
[]). Next, the same actions are repeated, albeit that the tt(delete) operator
is called without tt([]):
following situation, in which the destructor tt(~Strings) is modified so that
it tells us that it is called. In a tt(main) function an array of two
tt(Strings) objects is allocated by tt(new), to be deleted by tt(delete[]).
Next, the same actions are repeated, albeit that the tt(delete) operator is
called without tt([]):
verbinclude(-a examples/stringstoredelete.cc)
From the generated output, we see that the destructors of the individual
tt(Strings) objects are called when tt(delete[]) is used, while only the

View file

@ -64,7 +64,7 @@ context of the class tt(Person).
it() operator overloading can be used in situations where the operator is
commonly applied and no surprise is introduced when it's redefined. An example
where operator overloading is appropriately used is found in the class
tt(std::string): assiging one string object to another provides the
tt(std::string): assigning one string object to another provides the
destination string with a copy of the contents of the source string. No
surprises here.
it() in all other cases a member function should be defined instead of

View file

@ -91,7 +91,7 @@ again points to raw memory. This raw memory is then returned to the common
pool by tt(operator delete):
verbinclude(//DESTROY examples/strings.cc)
So far, so good. All is well as long as we're using but one object. What
So far, so good. All is well as long as we're using only one object. What
about allocating an array of objects? Initialization is performed as usual.
But as with tt(delete), tt(delete[]) cannot be called when the buffer was
allocated statically. Instead, when multiple objects were initialized using

View file

@ -7,7 +7,7 @@ address
hi(object: address) hi(address of objects) of the object for which the member
function was called. The tt(this) pointer is implicitly declared by each
member function (whether tt(public, protected), or tt(private)). The tt(this)
ponter is a constant pointer to an object of the member function's
pointer is a constant pointer to an object of the member function's
class. For example, the members of the class tt(Person) implicitly declare:
verb(
extern Person *const this;

View file

@ -24,7 +24,7 @@ Namespace declarations are context sensitive: when a tt(using namespace)
declaration is specified inside a compound statement then the declaration is
valid until the compound statement's closing curly bracket has been
encountered. In the next example a string tt(first) is defined without
explicit specfying tt(std::string), but once the compound statement has ended
explicit specifying tt(std::string), but once the compound statement has ended
the scope of the tt(using namespace std) declaration has also ended, and so
tt(std::) is required once again when defining tt(second):
verb(

View file

@ -1,5 +1,5 @@
As we've seen, (member) functions and variables of primitive data types can
defined with the tt(constexpr) modifier. What about class-type objects?
As we've seen, (member) functions and variables of primitive data types can be
defined using the tt(constexpr) modifier. What about class-type objects?
Objects of classes are values of class type, and like values of primitive
types they can be defined with the tt(constexpr) specifier. Constant
@ -43,10 +43,11 @@ trivial.
be maintained by its class's members. If a member is not declared with a
tt(constexpr) return value, then using that member does not result in a
constant-expression. If a member em(does) declare a tt(constexpr) return value
then that member's return value considered a tt(constexpr) if it is by itself
a constant expression function. To maintain its tt(constexpr) characteristics
it can refer to its classes data members em(only) if its object has been
defined with the tt(constexpr) modifier, as illustrated by the example:
then that member's return value is considered a tt(constexpr) if it is by
itself a constant expression function. To maintain its tt(constexpr)
characteristics it can refer to its classes data members em(only) if its
object has been defined with the tt(constexpr) modifier, as illustrated by the
example:
verb(
class Data
{

View file

@ -160,8 +160,8 @@ been relaxed. Starting at this standard, tt(constexpr) functions may
tt(static) or tt(thread_local) variables;
it() define variables without initializers;
it() use conditional statements (tt(if) and tt(switch));
it() use repetition statements statements, including the range-based
tt(for) statement;
it() use repetition statements, including the range-based tt(for)
statement;
it() use expressions changing the values of objects that are local to
the tt(constexpr) function;
)

View file

@ -31,7 +31,7 @@ dedicated to the definition of static data members, called ti(data.cc).
The data member tt(s_path[]), used above, could thus be
defined and initialized as follows in a file tt(data.cc):
verb(
include "directory.ih"
#include "directory.ih"
char Directory::s_path[200] = "/usr/local";
)

View file

@ -15,7 +15,7 @@ former constructor does not use any delimiters.
tt(ostream_iterator) may be used to copy information of a file to another
file. A subtlety here is that you probably want to use
tt(in.unsetf(ios::skipws)). It is used to clear the
hi(skipws)tt(ios::skipws) flag. As a consequence white space characters are
hi(skipws)tt(ios::skipws) flag. As a consequence whitespace characters are
simply returned by the operator, and the file is copied character by
character. Here is the program:
verbinclude(-a examples/ostreamiterator.cc)

View file

@ -51,9 +51,9 @@ following em(atoms):
In addition to these basic atoms, the following special atoms are available
(which can also be used in character classes):
itemization(
itt(\s): a white space character;
itt(\s): a whitespace character;
itt(\S): any character but a white space character;
itt(\S): any character but a whitespace character;
itt(\d): a decimal digit character;

View file

@ -6,7 +6,7 @@ before they can be used.
itemization(
ithtq(stof)(float stof(std::string const &str, size_t *pos = 0))
(Initial white space characters in tt(str) are ignored. Then the
(Initial whitespace characters in tt(str) are ignored. Then the
following sequences of characters are converted to a tt(float) value,
which is returned:
itemization(
@ -54,7 +54,7 @@ before they can be used.
value of type tt(long double).)
ithtq(stoi)(int stoi(std::string const &str, size_t *pos = 0,
int base = 10))
(Initial white space characters in tt(str) are ignored. Then all
(Initial whitespace characters in tt(str) are ignored. Then all
characters representing numeric constants of the number system whose
tt(base) is specified are converted to an tt(int) value, which is
returned. An optional + or - character may prefix the numeric

View file

@ -202,7 +202,7 @@ otherwise.
tt(delimiter) (or the end of the stream, whichever comes first) are
read from tt(istr) and are stored in tt(object). If the delimiter is
encountered it is removed from the stream, but is not stored in
tt(line).nl()
tt(object).nl()
If the delimiter is not found, tt(istr.eof) returns tt(true) (see
section ref(IOSTATES)). Since streams may be interpreted as tt(bool)
values (cf. section ref(IOSTATES)) a commonly encountered idiom to

View file

@ -63,7 +63,7 @@ object <= (object + 'x'); // true
quote(the insertion-operator (cf. section ref(CoutCinCerr)) may be used to
insert a tt(string) object into an tt(ostream), the extraction-operator may be
used to extract a string object from an tt(istream). The extraction operator
by default first ignores all white space characters and then extracts all
by default first ignores all whitespace characters and then extracts all
consecutively non-blank characters from an tt(istream). Instead of a string a
character array may be extracted as well, but the advantage of using a string
object should be clear: the destination string object is automatically resized

View file

@ -18,7 +18,7 @@ listing their capabilities is provided in this section, with subsequent
sections offering a detailed discussion. The bottom line: bf(C++) strings are
extremely versatile and there is hardly a reason for falling back on the bf(C)
library to process text. bf(C++) strings handle all the required memory
management and thus memory related problems, which is the #1 source of
management and thus memory related problems, which are the #1 source of
problems in bf(C) programs, can be prevented when bf(C++) strings are
used. Strings do come at a price, though. The class's extensive capabilities
have also turned it into a beast. It's hard to learn and master all its

View file

@ -49,7 +49,7 @@ string object's contents.
All tt(string)-member functions computing indices return the
predefined constant tt(string::npos) on failure.
The the ti(s) i(literal suffix) to indicate that a tt(std::string) constant is
The ti(s) i(literal suffix) to indicate that a tt(std::string) constant is
intended when a string literal (like tt("hello world")) is used. It can be
used after declaring tt(using namespace std) or, more specific, after
declaring

View file

@ -17,7 +17,7 @@ constants:
At line 3 a tt(promise) object is created, but its value is never
set. Consequently, it `breaks its promise' to produce a value: when
tt(main) tries to retrieve its value (in line 9) a tt(std::futue_error)
exception is thrown containing the the tt(future_errc::broken_promise)
exception is thrown containing the tt(future_errc::broken_promise)
value)
iti(future_already_retrieved)