TheOneAC

init


  • Home

  • Categories

  • Archives

  • Tags

Dynamic Memory

Posted on 2016-07-28   |   In C++

Dynamic Memory and Smart Pointers

shared_ptr:
init: make_shared< Type >(args); shared_ptr< Type >(q); p=q;
function :
p.unique() if count return 1 truw,else false.
p.use_count() return the number of object sharing with p.
make_shared. allocates and initializes an object in dynamic memory and returns a shared_ptr that points to that object.shared_ptr<string> p4 = make_shared<string>(10, '9');
new returns a pointer to the object it allocates:int *pi = new int;
By default, dynamically allocated objects are default initialized, which means that objects of built-in or compound type have undefined value
Like any other const, a dynamically allocated const object must be initialized.
const string *pcs = new const string;

1
2
int *p1 = new int; // if allocation fails, new throws std::bad_alloc
int *p2 = new (nothrow) int; // if allocation fails, new returns a null pointer

Functions that return pointers (rather than smart pointers) to dynamic memory put a
burden on their callers—the caller must remember to delete the memory

Dynamic memory managed through built-in pointers (rather than smart pointers) exists until it is explicitly freed.

three common problems with using new and delete

  1. Forgetting to delete memory. Neglecting to delete dynamic memory is known as a “memory leak,”
  2. Using an object after it has been deleted.
  3. Deleting the same memory twice.

dangling pointer:When we delete a pointer, that pointer becomes invalid.but the pointer continues to hold the address of the (freed) dynamic memory.
we cannot implicitly convert a built-in pointer to a smart pointer; we must use
the direct form of initialization to initialize a smart pointer

1
2
shared_ptr<int> p1 = new int(1024); // error: must use direct initialization
shared_ptr<int> p2(new int(1024)); // ok: uses direct initialization

use reset to assign a new pointer to a shared_ptr.

In particular, classes that are designed to be used by both C and C++ generally require the user to specifically free any resources that are used.

unique_ptr:”owns” the object which it points.
so it doesn`t support ordinary copy and assignment.
but can transfer ownership fron one (nonconst)unique_ptr to another by calling release or set.
// transfers ownership from p3 to p2 p2.reset(p3.release()); // reset deletes the memory to which p2 had pointed
only one unique_ptr at a time can point to a given object.
unique_ptr destroyed so the object it point to.
u.release() :return the pointer u had held and makes u null;
u.reset() :deletes the object to which i pointes;
u.reset(q) :if the built-in pointer q is supplied ,makes u pointe to that object.
u=nullptr; deletes the object to which u points,makes u null;
unique_ptr : bind to a pointer
http://stackoverflow.com/questions/6876751/differences-between-unique-ptr-and-shared-ptr

weak_ptr

not control the lifetime of the object it point to.
bind a weak_ptr to a shared_ptr not change the reference count of that shared_ptr.
weak:Once the last shared_ptr pointing to the object goes away, the object itself will be deleted. That object will be deleted even if there are weak_ptrs pointing to it.
The lock function checks whether the object to which the weak_ptr points still exists. If so, lock returns a shared_ptr to the shared object.

Dynamic Arrays

Classes that allocate dynamic arrays must define their own versions of these operations to manage the associated memory when objects are copied, assigned, and destroyed.
int *pia = new int[get_size()]; // pia points to the first of these ints
The size inside the brackets must have integral type but need not be a constant.

Allocating an Array Yields a Pointer to the Element Type

shared_ptrs provide no direct support for managing a dynamic array. If we want to use a shared_ptr to manage a dynamic array, we must provide our own deleter:
shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; }); sp.reset(); // uses the lambda we supplied that uses delete[] to free the array
classes that do not have default constructors cannot be dynamically allocated as an array.
allocator: provides type-aware allocation of raw, unconstructed, memory.
We must construct objects in order to use memory returned by
allocate. Using unconstructed memory in other ways is undefined.

Associative Containers

Posted on 2016-07-28   |   In C++

Associative containers support efficient lookup and retrieval by a key.

1
2
word.erase(std::remove_if(word.begin(), word.end(), ispunct),word.end());
$ remove_if move container to the end and return a partition iterater, erase the container from partition to the end.

the ordered containers—map, multimap, set, and multiset—the key type must define a way to compare the elements.
Callable objects passed to a sort algorithm (§ 10.3.1, p. 386) must meet the same requirements as do the keys in an associative container.
To use our own operation, we must define the multiset with two types: the key type, and the comparison type, which is a function pointer type that can point to compare function.
the data members of pair are public ,These members are named first and second,respectively. We access these members using the normal member access notation.
It is essential to remember that the value_type of a map is a pair and that we can change the value but not the key member of that pair.
Iterators for sets Are const,the keys in a set are also const.
The output of this program is in alphabetical order. When we use an iterator to traverse a map, multimap, set, or multiset, the iterators yield elements in ascending key order.
The insert members (Table 11.4 (overleaf)) add one element or a range of elements.

1
2
3
4
5
// four ways to add word to map word_count
word_count.insert({word, 1});
word_count.insert(make_pair(word, 1));
word_count.insert(pair<string, size_t>(word, 1));
word_count.insert(map<string, size_t>::value_type(word, 1));

Erasing Elements
c.erase(k) remove every element with the key k from c.
c.erase(p) remove the element denoted by the iterater p from c.
c.erase(b,e) remove the element in the range demoted by b and e and return e.

The map and unordered_map containers provide the subscript operator and a
corresponding at function,We cannot subscript a multimap or an unordered_multimap because there may be more than one value associated with a given key.
Subscripting a map behaves quite differently from subscripting an array or vector: Using a key that is not already present adds an element with that key to the map.

Operations to Find Elements in an Associative Container
c.find(k) return iterator to the first element with the key k or the off-the-end iterator.
c.count(k) return the number of elements with key k.
c.lower_bound(k) return an iterator to the first element with key not less than k.
c.upper_bound(k) return an iterator to the first element with key greater than k.
c.equal_range(k) return a pair of iterator denoting the elements with key k,if k is not present, both menbers are c.end().
If the key is present, then the first iterator refers to the first instance of the key and the second iterator refers one past the last instance of the key. If no matching element is found, then both the first and second iterators refer to the position where this key can be inserted.

For the map and unordered_map types,using a subscript has an important side effect: If that key is not already in the map, then subscript inserts an element with that key.
When a multimap or multiset has multiple elements of a given key, those elements will be adjacent within the container.

Hash and Unordermap???

C++ Primier Plus Generic Algorithms

Posted on 2016-07-26   |   In C++

find algorithm: auto result = find(vec.cbegin(), vec.cend(), val);
It returns an iterator to the first element that is equal to that value.
use the library begin and end functions to pass a pointer to the first and one past the last elements in ia.

1
2
3
4
5
6
7
int ia[] = {27, 210, 12, 47, 109, 83};
int val = 83;
//int* result = find(begin(ia), end(ia), val);
// count(v.cbegin(), v.cend(), value)
// int sum = accumulate(vec.cbegin(), vec.cend(), 0);
The accumulate function takes three arguments. The first two specify a
range of elements to sum. The third is an initial value for the sum.

equal(roster1.cbegin(), roster1.cend(), roster2.cbegin());
fill(vec.begin(), vec.end(), value);
fill(vec.begin(), vec.begin() + vec.size()/2, value);
fill_n(dest, n, val)
Algorithms that write to a destination iterator assume the destination is large enough to hold the number of elements being written.
back_inserter takes a reference to a container and returns an insert iterator bound to that container. When we assign through that iterator, the assignment calls push_back to add an element with the given value to the container.

1
2
3
vector<int> vec; // empty vector
auto it = back_inserter(vec); // assigning through it adds elements to vec
*it = 42; // vec now has one element with value 42

auto ret = copy(begin(a1), end(a1), a2);
The value returned by copy is the (incremented) value of its destination iterator. That is, ret will point just past the last element copied into a2.
replace(ilst.begin(), ilst.end(), 0, 42);
This call replaces all instances of 0 by 42. If we want to leave the original sequence unchanged, we can call replace_copy.
back_inserter is a insert iterator, what iterator adaptor that generates an iterator that uses a container operation to add elements to a given container.
the algorithms don’t change the size, but the iterator can change it by using the container operation.

Eliminating Duplicates

1
2
3
4
5
6
7
8
9
10
void elimDups(vector<string> &words)
{
// sort words alphabetically so we can find the duplicates
sort(words.begin(), words.end());
// unique reorders the input range so that each word appears once in the
// front portion of the range and returns an iterator one past the unique range
auto end_unique = unique(words.begin(), words.end());
// erase uses a vector operation to remove the nonunique elements
words.erase(end_unique, words.end());
}

  1. The library algorithms operate on iterators, not containers. Therefore, an
    algorithm cannot (directly) add or remove elements.
  2. To actually remove the unused elements, we must use a container operation

A lambda expression represents a callable unit of code. It can be thought of as an unnamed, inline function.

lambda

http://www.cnblogs.com/knowledgesea/p/3163725.html
[capture list] (parameter list) -> return type { function body }
The capture list directs the lambda to include information needed to access those variables within the lambda itself.
The capture list is used for local nonstatic variables only; lambdas can use local statics and variables declared outside the function directly.
When we capture a variable by reference, we must ensure that the variable exists at the time that the lambda executes.
By default, a lambda may not change the value of a variable that it copies by value.
be able to change the value of a captured variable, we must follow the parameter list with the keyword mutable.

Insert Iterators
• back_inserter (§ 10.2.2, p. 382) creates an iterator that uses push_back.
• front_inserter creates an iterator that uses push_front.
• inserter creates an iterator that uses insert. This function takes a second argument, which must be an iterator into the given container. Elements are inserted ahead of the element denoted by the given iterator.

it is not possible to create a reverse iterator from a forward_list or a stream iterator.

List the five iterator categories and the operations that each supports.
• Input iterators : ==, !=, ++, , ->
• Output iterators : ++,

• Forward iterators : ==, !=, ++, , ->
• Bidirectional iterators : ==, !=, ++, –,
, ->
• Random-access iterators : ==, !=, <, <=, >, >=, ++, –, +, +=, -, -=, -(two iterators), , ->, iter[n] == (iter + n)

The list member versions should be used in preference to the generic algorithms for lists and forward_lists.
a crucially important difference between the list-specific and the generic versions is that the list versions change the underlying container.

C Primier Plus Sequential Container

Posted on 2016-07-25   |   In C++

vector deque list forward-list array string
string and vector hold their elements in contiguous memory.
it is best to use vector unless there is a good reason to prefer another container.
the predominant operation of the application (whether it does more access or more insertion or deletion) will determine the choice of container type.
The exception is that the forward_list iterators do not support the decrement (–) operator.
a reverse iterator is an iterator that goes backward through a
container and inverts the meaning of the iterator operations. For example, saying ++ on a reverse iterator yields the previous element.

When write access is not needed, use cbegin and cend.
When we initialize a container as a copy of another container, the container type and element type of both containers must be identical.

1
2
3
4
5
6
7
list<string> authors = {"Milton", "Shakespeare", "Austen"};
vector<const char*> articles = {"a", "an", "the"};
list<string> list2(authors); // ok: types match
deque<string> authList(authors); // error: container types don't match
vector<string> words(articles); // error: element types must match
// ok: converts const char* elements to string
forward_list<string> words(articles.begin(), articles.end());

Sequential Container Size-Related Constructors

1
2
3
4
vector<int> ivec(10, -1); // ten int elements, each initialized to -1
list<string> svec(10, "hi!"); // ten strings; each element is "hi!"
forward_list<int> ivec(10); // ten elements, each initialized to 0
deque<string> svec(10); // ten elements, each an empty string

The constructors that take a size are valid only for sequential containers; they are not supported for the associative containers.
To use an array type we must specify both the element type and the size:

1
2
array<int, 10>::size_type i; // array type includes element type and size.
array<int>::size_type j; // error: array<int> is not a type.

Six Way to Create and Initialize a vector

1
2
3
4
5
6
vector<int> vec; // 0
vector<int> vec(10); // 0
vector<int> vec(10,1); // 1
vector<int> vec{1,2,3,4,5}; // 1,2,3,4,5
vector<int> vec(other_vec); // same as other_vec
vector<int> vec(other_vec.begin(), other_vec.end()); // same as other_vec

  1. The constructor that takes another container as an argument (excepting array) assumes the container type and element type of both containers are identical.
  2. The constructor that takes two iterators as arguments does not require the container types to be identical. Moreover, the element types in the new and original containers can differ as long as it is possible to convert the elements we’re copying to the element type of the container we are initializing.

Unlike built-in arrays, the library array type does allow assignment,the array type does not support assign and it does not allow assignment from a braced list of values.
Using assign (Sequential Containers Only)

1
2
3
4
5
list<string> names;
vector<const char*> oldstyle;
names = oldstyle; // error: container types don't match
// ok: can convert from const char*to string
names.assign(oldstyle.cbegin(), oldstyle.cend());

after swap,with the exception of string,iterators, references, and pointers into the containers are not invalidated.but a call to swap on a string may invalidate iterators, references and pointers.

Read more »

C Primier Plus IO Library

Posted on 2016-07-25   |   In C++

No Copy or Assign for IO Objects

Functions that do IO typically pass and return the stream through references. Reading or writing an IO object changes its state, so the reference must not be const.
The library lets us ignore the differences among these different kinds of streams by using inheritance
There are two other similar manipulators: flush and ends.
flush flushes the stream but adds no characters to the output; ends inserts a null character into the buffer and then flushes it

1
2
3
4
5
6
7
cout << "hi!" << endl; // writes hi and a newline, then flushes the buffer
cout << "hi!" << flush; // writes hi, then flushes the buffer; adds no data
cout << "hi!" << ends; // writes hi and a null, then flushes the buffer
cout << unitbuf; // all writes will be flushed immediately
// any output is flushed immediately, no buffering
cout << nounitbuf; // returns to normal buffering

Output buffers are not flushed if the program terminates abnormally.
Tying Input and Output Streams Together:
When an input stream is tied to an output stream, any attempt to read the input stream will first flush the buffer associated with the output stream.
To tie a given stream to a new output stream, we pass tie a pointer to the new stream. To untie the stream completely, we pass a null pointer. Each stream can be tied to at most one stream at a time. However, multiple streams can tie themselves to the same ostream

1
2
3
4
5
6
cin.tie(&cout); // illustration only: the library ties cin and cout for us
// old_tie points to the stream (if any) currently tied to cin
ostream *old_tie = cin.tie(nullptr); // cin is no longer tied
// ties cin and cerr; not a good idea because cin should be tied to cout
cin.tie(&cerr); // reading cin flushes cerr, not cout
cin.tie(old_tie); // reestablish normal tie between cin and cout

The only way to preserve the existing data in a file opened by an ofstream
is to specify app or in mode explicitly.
File Mode Is Determined Each Time open Is Called.

C Primier Plus Class

Posted on 2016-07-21   |   In C++

Functions defined in the class are implicitly inline.
every member function must be declared inside its class.
Member functions access the object on which they were called through an extra, implicit parameter named this.
this is intended to always refer to “this” object(current function), this is a const pointer
const after the parameter list of a member function. A const following the parameter list indicates that this is a pointer to const

1
std::string isbn() const { return this->bookNo; }

The name of a member defined outside the class must include the name of the class of which it is a member
Dedining a function to Return “this” Object

1
2
3
4
5
6
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold; // add the members of rhs into
revenue += rhs.revenue; // the members of ''this'' object
return *this; // return the object on which the function was called
}

nonmember functions that are part of the interface of a class should be declared in the same header as the class itself.

Constructer

constructors may not be declared as const .When we create a const object of a class type, the object does not assume its “constness” until after the constructor completes the object’s initialization.
The compiler generates a default constructor automatically only if a class
declares no constructors
Class:use class to define the class are similar to struct ,the only difference is the default level.
A class may define members before the first access specifier.
To members before the first access specifier, for struct they are public,for class they are private.
private:accessible to the menber function not accessible to code that use the class.
A class allow another class or function to access its nonpublic menbers by making that class or function a friend.
Each class controls which classes or functions are its friends.friendship is not transitive.
a friend declaration affects access but is not a declaration in an ordinary sense,if we define the function inside the class, we must still provide a declaration outside of the class itself to make that function visible
We must use the constructor initializer list to provide values for members that are const, reference, or of a class type that does not have a default constructor.
Members are initialized in the order in which they appear in the class definition.

  1. It is a good idea to write constructor initializers in the same order as the
    members are declared. Moreover, when possible, avoid using members to initialize other members.
  2. it is a good idea write member initializers to use the constructor’s
    parameters rather than another data member from the same object.

Only One Class-Type Conversion Is Allowed

1
2
3
4
5
6
7
8
9
10
11
12
13
$ Now, neither constructor can be used to implicitly create a Sales_data object.
$ The explicit keyword is meaningful only on constructors that can be called with a single argument.
$ The explicit keyword is used only on the constructor declaration inside
the class.
class Sales_data {
public:
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p):
bookNo(s), units_sold(n), revenue(p*n) { }
explicit Sales_data(const std::string &s): bookNo(s) { }
explicit Sales_data(std::istream&);
// remaining members as before
};

* An aggregate class (§ 7.5.5, p. 298) whose data members are all of literal type is a literal class??

static Class Members

a member is associated with the class by adding the keyword static to its
declaration.
Even though static members are not part of the objects of its class, we can use an object, reference, or pointer of the class type to access a static member:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Account {
public:
void calculate() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
};
Account ac1;
Account *ac2 = &ac1;
// equivalent ways to call the static member rate function
r = ac1.rate(); // through an Account object or reference
r = ac2->rate(); // through a pointer to an Account object

As with any class member, when we refer to a class static member outside
the class body, we must specify the class in which the member is defined.
The static keyword, however, is used only on the declaration inside the
class body.
we must define and initialize each static
data member outside the class body. and a static data member may be defined only once.

  1. a static data member can have incomplete type
  2. a static data member can have the same type as the class type of which
    it is a member.
  3. we can use a static member as a default argument

C++ Primier chapter six:function

Posted on 2016-07-19   |   In C++

in C++ function can be overload, the same name may be from different function.
function call: initialize the function`s parameter, transfer control to the function.
local static object is initialized before the first execution ,not destroyed untill the function ends.
Passing argument by value:the value of the initiaizer is copied,changes made to the variable have no effect on the initialzizer.
Pointer Parameter :copy the value of another pointer,but can change the value of the object by assignning through the pointer.
Passing Argument byreference:changes made to the reference are made to the object to which referencr refers.
Using Reference Parameters to Return Additional Information:
return multiple results effectively.
const Parameter and Arguments:top-level const that applt to the object itself.
Two Way to array:

  1. print(const int beg, const int end)
  2. print(const int ia[], size_t size)
1
2
int *matrix[10]; // array of ten pointers
int (*matrix)[10]; // pointer to an array of ten ints

initializer_list: all const value ,no way to change the value of an element.
begin():a pointer to the first element.

end():an off-the-end pointer one past the last element.

**Swap In Reference

1
2
3
4
5
6
7
8
9
10
11
void swap(int &v1, int &v2)
{
// if the values are already the same, no need to swap, just return
if (v1 == v2)
return;
// if we're here, there's work to do
int tmp = v2;
v2 = v1;
v1 = tmp;
// no explicit return necessary
}

return reference must not refer to an local object,as well as pointer.
Calls to functions that return references are lvalues; other return types
yield rvalues

Overlaod function

Functions that have the same name but different parameter lists and that appear in the same scope are overloaded
Overload function must differ in hte number or the types of their aprameters.
Top-level const has no effect on the objects that can be passed to the function.
function taking const and nonconst reference or pointers have different parameters.
In C++, name lookup happens before type checking.
the compiler first looks for a declaration of that name.
Once a name is found, the compiler
ignores uses of that name in any outer scope’

Default Argument Declarations
any subsequent declaration can add a
default only for a parameter that has not previously had a default specified
Inline Function:remove the run-time of calling a function.
put the key word inline before the return type.
A constexpr function is not required to return a constant expression.


Read more »

chapter four~five

Posted on 2016-07-17   |   In C++

Parentheses Override Precedence and Associativity

1
2
3
4
5
6
7
8
Managing Compound Expressions
1. When in doubt, parenthesize expressions
to force the grouping that the
logic of your program requires.
2. If you change the value of an operand,
don’t use that operand elsewhere
in the same expresion

Assignment is right associative.
Shift Operators (aka IO Operators) Are Left Associative.
sizeof operator returns the size, in bytes, of an expression or a type name.
right associative
sizeof expr :not evaluate the value but return the type returned by the given expression
sizeof a reference type returns the size of an object of the referenced type
sizeof an array is the size of the entire array

A block is not terminated by a semicolon

Exception handling

Throw :raise an exception and terminates the current function.
Try: deal with exception. one or more catch clauses

1
2
3
try { program-statements}
catch (exception-declaration) { handler-statements}
catch (exception-declaration) { handler-statements}

onece one catch executed,execution continues with the statement immediately following the last catch clause of the try block
variable declared inside a try block are inaccessible outside the block as well as to catch clauses.
If a program has no try blocks and an exception occurs, then terminate is called and the program is exited.

Comments:exception and leakage

C Primier Plus --chapter three

Posted on 2016-07-16   |   In C++

Namespace

std::cin use the name from the namespace std.
using namespacename::name;
after the using declaration we can use the name directly.
A Separate using Declaration Is Required for Each Name

Each using declaration introduces a single namespace member


initialization of string

1
2
3
4
string s1; // default initialization; s1 is the empty string
string s2 = s1; // s2 is a copy of s1
string s3 = "hiya"; // s3 is a copy of the string literal
string s4(10, 'c'); // s4 is cccccccccc

os<< s Write s onto output stream os.return os.
is>> s Reads whitespace-seperated string from is into s.return is.
getline(is,s) Reads a line of input from is to s.return is.
s.empty() Returns true if s is empty; otherwise returns false.
s.size() Returns the number of characters in s.
s[n] Returns a reference to the char at position n in s;position start at 0.
s1+s2 Returns a string that is concatenation of s1 and s2.
!= ,<,<=,>,>= Comparisons are case-sensitive and use dictionary.

1
2
3
4
The string input operator reads and discards any leading whitespace
(e.g., spaces, newlines, tabs). It then readscharacters until the next
whitespace character is encountered
Reading an Unknown Number of strings

getline() reads to (including)the first newline,but not store in the string.
empty:member function of string``return bool

size()
return string::size_type

always use auto or decltype to let the compiler to provide the approriate

1
2
DEV-C++支持C++11标准:
Tools>-Compiler Option >-Code Generation >- Language standart
Read more »

C Primier Plus --chapter two

Posted on 2016-07-15   |   In C++

Top-Level const

A pointer who is const is top-level const,
and the object it point to is const ,it is low-level
pointer must point to an object,not a value.
pointer pointe to an const object may not be initialize,but const pointer must be intialized when defined.

  • Top-level indicates that an object itself is const, and appear in any object type.
  • Low-level const only appear in the base type of compiund type such as pointer and reference
  • when copy an object top-level const will be ipnored
  • when copy an object low-level const must be the same ,because it cann’t be ignored
    Read more »
1…456
TheOneAC

TheOneAC

生如逆旅 一苇可航

51 posts
20 categories
33 tags
GitHub Email Quora 知乎
© 2016.7.14 - 2017 TheOneAC
Powered by Hexo
Theme - NexT.Mist