C++初始化变量有好几种方法:
int a=0;
int a={0};
int a{0};
都可以。
如果要在多个文件中使用同一个变量,就必须将声明和定义分离。此时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,却绝对不能重复定义。
如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量(任何包含了显式初始化的声明即成为定义。):
extern int i; // 声明i而非定义i
int j; // 声明并定义j
(1)引用被创建的同时必须被初始化(指针则可以在任何时候被初始化,最好也初始化,否则容易出错)。
(2)一旦引用被初始化,就不能改变引用的关系(指针则可以随时改变所指的对象)。
它的作用是为变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写:
int a;
int &b=a;
int *p= &a; 这里&是取地址符。表示指针p指向(本语句等价于
int *p; p= &a;)
这就表明了b是a的“引用”,即a的别名。经过这样的声明,使用a或b的作用相同,都代表同一变量。
int &b=a2;//企图使b变成a2的别名(引用)是不行的。这样是错误的。
引用不是一个对象,所以不能定义引用的引用。
const char *p = "hello world";
指针指向的变量不可以改变,指针本身可以改变(即指向常量的指针)
这种情况下,以下语句是合法的:
char c = *p;
p++;
以下语句不合法:
*p = 'a';
p[5] = 'b';
char *const p表示指针指向的变量可以改变,但指针本身不能改变。
比如
int i=4;
int *const p = &i;
那么*p = 5;是合法的,p++是不合法的
const char *const p
两者都不可以改变。
理解这些声明的技巧在于,查看关键字const右边来确定什么被声明为常量 ,如果该const的右边是类型,则值是常量(底层const);如果const的右边是指针变量,则指针本身是常量(顶层const)。赋值拷贝的时候要特别注意底层const,一般来说,非常量可以赋值给常量,反之则不行。
例如const int *a = int *b; 反之不行。
C++ 11中引入的auto主要有两种用途:自动类型推断和返回值占位。auto在C++ 98中的标识临时变量的语义,由于使用极少且多余,在C++ 11中已被删除。
auto自动类型推断,用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推断,可以大大简化我们的编程工作。下面是一些使用auto的例子。
auto a; // 错误,没有初始化表达式,无法推断出a的类型
auto int a = 10 // 错误,auto临时变量的语义在C++ 11中已不存在
auto a = 10
auto c = 'A'
auto s("hello");
vector<</span>int> vctTemp;
auto it = vctTemp.begin();
auto ptr = [](){ cout << "hello world" << endl; };
另外,在使用模板技术时,如果某个变量的类型依赖于模板参数,不使用auto将很难确定变量的类型(使用auto后,将由编译器自动进行确定)。下面是一个具体的例子。
template <</span>class T, class U>
void Multiply(T t, U u)
{
auto v = t*u;
}
auto返回值占位,主要与decltype配合使用,用于返回值类型后置时的占位。
template <</span>class T, class U>
auto Multiply(T t, U u)->decltype(t*u)
{
typedef decltype(t*u) NewType;
NewType *pResult = new NewType(t*u);
return *pResult;
}
至于为什么需要将返回值类型后置,这里简单说明一下。如果没有后置,则函数声明为decltype(t*u) Multiply(T t, U u),但此时模板参数t和u还未声明,编译无法通过。
如果这个表达式是个函数,decltype
给出的类型为函数返回值的类型。
[cpp] view plaincopy
int add(int i, int j){ return i+j; }
decltype(add(5,6)) var = 5;//Here the type of var is return of add() -> which is int
非常重要的标记一下,decltype
不会执行表达式而auto会,他仅仅推论一下表达式的类型。
int foo(){}
decltype( foo() ) x; // x is an int and note that
// foo() is not actually called at runtime
头文件不应包含using 声明
string s1="hello", s2="world";
string s3=s1+","+s2;
string s4 =s1+",";
string s4 =s1+s2;
而+两侧运算对象至少一个是string类型:
string s6="hello"+","+s2;
//错误, 不能把字面值直接相加
基于范围的for 语句
遍历给定序列中每个元素并操作
简单例子:把string对象中的字符每行一个个的输出出来
string str("some strings");
for (auto c : str)
cout<<c<<endl;
这里使用auto 让编译器来决定c变量的类型,这里是char型
但如果想改变string 对象中的字符值,循环变量必须定义成引用
比如将string对象字符全变为大写
string str("some strings");
for (auto &c : str)
c=toupper(c);
cout<<s<<endl;
这里toupper函数是定义在〈cctype〉头文件中的处理string中的某个特定字符的集合。
标准模板库类型vector 表对象的集合。一般用{ }初始化,不容易错。
vector 〈string〉 v1{"a","ab","abc"};
除了以下情况用()初始化
vector 〈string〉 svec(10, "hi!"); 表示10个string 类型的元素,每个都被初始化为"hi!"。
vector 〈int〉svec(10); 表示10个int 类型的元素,每个都被初始化为0。
vector 〈int〉svec(10,1); 表示10个int 类型的元素,每个都被初始化为1。
如果这时使用{}
vector svec{10};
表示1个int类型元素,该元素是10。
vector 〈int〉svec{10,1}; 表示2个int类型元素,分别是10和1。
它的成员函数push_back()
vector 〈int〉 v2;
for(int i=0; i!=100; ++i)
v2.push_back(i); //依次将整数值放到v2的尾端 。。使用C++,在for循环中要习惯使用!=而不是﹤
迭代器
(1) 每种容器类型都定义了自己的迭代器类型,如vector:std::cout << *iter; *iter = 5; *iter = *iter + 5; |
constexpr size_t rowCnt = 3, colCnt = 4;
int ia[rowCnt][colCnt]; // 12 个未初始化的元素
// 对于每一行
for (size_t i = 0; i != rowCnt; ++i) {
//对于行内的每一列
for (size_t j = 0; j != colCnt; ++j) {
// 将元素的位置索引作为它的值
ia[j] = i * colCnt + j;
}
}
外层的for循环遍历ia的所有元素,注意这里的元素是一维数组;内层的for循环则遍历那些一维数组的整数元素。此例中,我们将元素的值设为该元素在整个数组中的序号。
使用范围 for语句处理多维数组
由于在C++11新标准中新增了范围for语句,所以前一个程序可以简化为如下形式:
size_t cnt = 0;
for (auto &row : ia)
// 对于外层数组的每一个元素
for (auto &col : row) {
// 对于内层数组的每一个元素
col = cnt;
// 将下一个值赋给该元素
++cnt;
// 将 cnt加1
}
因为要改变元素的值,所以得把控制变量row和col声明成引用类型。
标准库函数 begin和end 跟容器的bengin和end 成员函数功能差不多。不过毕竟数组不是类类型,所以不太一样。
int ia[] = {0,1,2,3,4,5,6,7};
int *beg = begin(ia); //指向ia的首元素
int *last = end(ia); // 指向数组ia的最后一个元素的下一个位置。
位与,位或,位异或
7&8 = 0000 0111 & 0000 1000 = 0000 0000 = 0
7|8 = 0000 0111 | 0000 1000 = 0000 1111 = 15
7^8 = 0000 0111 ^ 0000 1000 = 0000 0111 = 7
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |