Container & Function
Reference : https://note.hobbitqia.cc/OOP/oop3/#for-each-loop
Container¶
Collection objects are objects that can store an arbitrary number of other objects.
- 在 C++ 中,容器在 STL 中
- STL = Standard Template Library
Vector¶
Example.1¶
#include <iostream>
using namespace std;
#include<vector>
int main(){
vector<int> x;
for (int a=0;a<1000;a++){
x.push_back(a);
}
vector<int>::iterator p;
for(p=x.begin();p<x.end();p++)
cout << *p << " ";
return 0;
}
int main(){
vector<int> x;
for(int a=0;a<100;a++){
x.push_back(a);
}
cout << x.size()<<endl
vector<int>::iterator p;
for(auto k : x){
cout << k << " ";
}
cout << endl;
return x;
}
-
iterator : class inside vector
-
generic classes
vector<string> notes;
Have to specify two types
It is able to increase its internal capacity as required: as more items are added, it simply makes enough room for them
It keeps its own private count of how many items it is currently storing. Its size method returns the number of objects currently stored in it
It maintains the order of items you insert into it.You can later retrieve them in the same order.
Basic Vector Operations¶
- Constructors
- Simple Methods
- Iterators
- Element access
- Add/Remove/Find
- Insert & erase -- use iterator
Example.2¶
int main(){
vector<Student> ss //Student is a class
Student s(1);
ss.push_back(s);
s.x = 10; // does not change ss[0]
}
int main(){
vector<Student*> ss
Student s(1);
ss.push_back(&s);
s.x = 10; //will change(obviously)
}
Operations¶
- 对于,比如
<vector>
可以向任意下标赋值,不会报错,但是这不会改变.size() .back()
等 ,所以实际上我们要用push_back()
等去insert
List¶
- Dif :
p!=s.end()
#include <iostream>
using namespace std;
#include<list>
int main(){
list <int> L;
for(int i=0;i<5;i++){
L.push_back(i);
}
L.erase(++L.begin());
copy(L.begin(),L.end(),ostream_iterator<int>(cout,","));
}
通常用vector : 更节约空间,除非需要大量增加,删除
Maps¶
Hash
#include <map>
map<long,int> root;
root[4] = 2;
root[1000000] = 1000;
long l;
cin >> l;
if (root.count(l))
cout<<root[l]
else cout<<“Not perfect square”;
Pitfalls¶
- Erase for Iterator !
list<int> L;
list<int>::iterator li;
li = L.begin();
L.erase(li);
++li; // WRONG
// Use return value of erase to advance
li = L.erase(li); // RIGHT
- Inadvertently inserting into
map<>
if (foo["bob"]==1)
//silently created entry “bob”
//Solutions: Use count() to check for a key without creating a new entry. if ( foo.count("bob") )
Function¶
Function Overloading¶
void print(char * str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width); // #3
void print(int i, int width); // #4
void print(char *str); // #5
print("Pancakes", 15);
print("Syrup");
print(1999.0, 10);
print(1999, 12);
print(1999L, 15);
- Can go wrong
Default arguments¶
A default argument is a value given in the declaration that the compiler automatically inserts if you donʼt provide a value in the function call.
int harpo(int n, int m = 4, int j = 5);
int chico(int n, int m = 6, int j); // illegal
//To define a function with an argument list, defaults must be added from right to left.
int groucho(int k = 1, int m = 2, int n = 3);
beeps = harpo(2);
beeps = harpo(1,8);
beeps = harpo(8,7,6);
- Default arguments Cannot write in the def part, but the 函数声明! part.
Friend [Access Control]¶
struct X{
private:
int x;
public :
void initialize();
friend void g(X*,int);
friend void Y::f(X*);
friend struct Z;
friend void h();
};
Overhead for a function call¶
Inline Functions¶
- An inline function is expanded in place , like a preprocessor macro , so the overhead of the function call is eliminated.
- Def for inline is "Actually 声明"
- 当调用函数时,编译器把函数替换到实际位置
- 整个inline函数放入头文件
- 如果放在cpp里,那么只能local使用
- 内联函数应在头文件中定义,以确保在所有使用它的翻译单元(编译单元)中都能看到函数体。
- 递归函数一般不适合内联,因为编译器无法预测递归深度。
- 内联函数不应过大,否则会导致代码膨胀,失去内联带来的性能提升。
// .h File!!!
class Point{
...
public:
inline void print(string & msg = "");
};
inline void Point::print(string & msg = ""){
...
}
- While 可执行程序size 变大 tradoff for effectiveness
- Better for 宏macro :check
- Compiler will automatically do inline or undo inline
Tradeoff¶
- 将成员函数的定义写在声明内,就会自动 inline. 也可以在 body 的地方加上 inline.
Const¶
const int a = 6
-- not changable variable
- value must be initialized.
const int bufsize = 1024;
-
Unless you make an explicit extern declaration , like
extern const int bufsize;
-
Compiler to make sure that it will not be changed.
Connot be optimized : (remain variables)
- Global variables.
- 函数参数
- 成员变量
const int x = 123; // const, literal
x = 27; // illegal!
x++; // illegal!
int y = x; // ok, copy const to non-const
y = x; // ok, same thing
const int z = y; // ok, const is safer
const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // Illegal(in C++98)
struct S { int i, j; };
const S s[] = { { 1, 2 }, { 3, 4 } };
double d[s[1].j]; // Illegal
- It is possible to use
const
for aggregates, but storage will be allocated. In these situations,const
means "a piece of storage that cannot be changed."
However,the value cannot be used at compile time because the compiler is not required to know the contents of the storage at compile time.
Pointer¶
char * const q = "abc"; // q is const
*q = 'c'; // ERROR
// char a[] = "abc"; *q = 'c' is ok.
q++; // ERROR
const char *p = "ABCD"; // (*p) is a const char
*p = 'b'; // ERROR! (*p) is the const
- Quiz
string p1("Fred");
const string* p = &p1; // p1 cannot be changed through p.
string const* p = &p1; // like the first one.
string *const p = &p1; // p cannot be changed.only point to p1.
String Literals¶
char *s = "Hello"; //can be compile but bus error because actually const char *s
// Add const compile will not pass.
s[0] = 'K';
printf("%s\n",s);
// Write in an array
char s[] = "Hello, world!";
Const Object¶
Compiler Will ERROR:
- Public member variable
- its member function will change the variable
Thus,when we write all the member functions,SPECIFY CONST! For Compiler to know if it will change the value of member variables!
int Date::set_day(int d) {
//...error check d here...
day = d; // ok, non-const so can modify
}
int Date::get_day() const {
day++; // ERROR modifies data member
set_day(12); // ERROR calls non-const member
return day; // ok
}
const
定义的对象,只能调用带const
属性的成员函数。-
const
必须保证成员变量有初始值!默认构造函数. -
Overload (const can distinguish the two functions.),会根据对象调用时是否
const
来决定调用哪个成员函数
事实上 const
后的成员函数参数,相当于 const A *this
, 而不加 const 就只是 A *this
.
const
作用在隐藏参数 A* this
- member of class is constant : must be initialized by the constructor(const) or the C++11 way
Static¶
- 静态本地变量实际上是全局变量,被存储在静态内存中
只在第一次访问[只在第一次被执行到的时候]时被构造
出现在全局变量/函数前,表示访问限制,只有当前文件可以访问
在程序结束后析构
- Global Objects
全局变量的构造发生在 main()
之前,在 main()
或者 exit()
之后析构
但是不同编译单元的全局变量,如果存在依赖关系,但这是无法保证的
最好不在C++使用global variable
- 静态成员变量和静态本地变量是一样的
访问受限,限于类内部,实际上是全局变量。
在这个类内所有的对象都维持相同的值,对象 A 修改了那么对象 B 的这个变量的值也会改变
- 静态成员函数没有 this, 不能调用非静态成员变量,也不能访问非静态函数
可以在没有创建类的对象的时候就能调用静态成员函数
#ifndef _STAT_MEM_
#define _STAT_MEM_
class StatMem{
public:
int getHeight(){return m_h;}
void setHeight(int i){m_h = i}
int getWeight(){return m_w;}
void setWeight(int i){m_w = i;}
static int m_h;
int m_w;
}
#endif
- 一个静态的全局变量,必须在头文件对应的.cpp中重新
且不能再加static
Namespace¶
Example
// Mylib.h
namespace XLib {
void x();
void y();
}
namespace YLib {
void y();
void z();
}
//Main
void main() {
using namespace XLib;
using namespace YLib;
x(); // OK
y(); // Error: ambiguous
XLib::y(); // OK, resolves to XLib
z(); // OK
}
Namespace aliase¶
Namespace composition¶
- Compose new namespaces using names from other ones.
- Using-declarations can resolve potential clashes.
- Explicitly defined functions take precedence.
namespace first {
void x();
void y();
}
namespace second {
void y();
void z();
}
namespace mine {
using namespace first;
using namespace second;
using first::y(); // resolve clashes to first::x()
void mystuff();
// ...
}
Namespaces are open¶
//header1.h
namespace X {
void f();
}
// header2.h
namespace X {
void g(); // X now has f() and g();
}
Namespace selection¶
- Compose namespaces by selecting a few features from other namespaces.
- Choose only the names you want rather than all.
- Changes to "orig" declaration become reflected in "mine".
Appendix¶
C++
链接器不去做参数类型的判断,那么怎么做overload , namespace?
f(int a,float b)
will turn into _f_int_double_()
namespace func(void f();) _func_f_()
- 老版本
C
编译产生的是不带下划线的 solution:
创建日期: 2024年1月29日 23:37:55