Skip to content

Commit 52d317c

Browse files
committed
update: learncpp_5
1 parent 008af8e commit 52d317c

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

content/posts/learncpp_4/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ const int& a = getTempVar();
9191

9292
### 与auto相结合
9393

94-
- 顶级`const`: 指的是对于此对象修饰的`const`
94+
- 顶级`const`: 指的是修饰此别名/对象的`const`
9595
- 低级`const`: 指的是被引用绑定/被指针指向的`const`
9696

9797
指针可以同时拥有两种`const`,但是引用不行,因为引用不是对象。
@@ -121,7 +121,7 @@ constexpr const auto& ref{getConstRef()};
121121
- `auto* const`
122122
- `const auto* const`
123123
124-
这样就很明显的看出,在*左边的意义是指向常量,在右边的意义是常量的指针,事实上既然都`auto`了,也不差这几个关键字吧?我其实比较担心`auto`不够只能这个问题
124+
这样就很明显的看出,在*左边的意义是指向常量,在右边的意义是常量的指针,事实上既然都`auto`了,也不差这几个关键字吧?我其实比较担心`auto`不够智能这个问题
125125
126126
> 为什么呢?
127127

content/posts/learncpp_5/index.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,96 @@ template <typename T>
6767
using Coord = Pair<T>; // Coord is an alias for Pair<T>
6868
```
6969

70+
##
71+
72+
类的成员变量,成员函数是隐式内联的,所以放在头文件中被多个源文件引用的时候,不违反ODR原则。
73+
74+
在类中,不强制声明语句位于使用之前,只要他们都在同一个类中即可。
75+
76+
调用常量类对象内部的函数,要将此成员函数声明为`const`
77+
78+
```cpp
79+
void foo() const {
80+
//...
81+
}
82+
```
83+
84+
`struct``class`仅有的差异:`struct`默认使用`public:`,而`class`默认使用`private:`。在继承性上也是这样。
85+
86+
`protect:`允许派生的类访问,其可见性介于两者之间。
87+
88+
89+
### 推荐实践
90+
91+
1. 不要让成员函数返回引用,否则将会使得成员变量被以外修改。
92+
2. 不推荐使用成员函数,为了使类的实现更加简洁。
93+
94+
### 成员初始化列表
95+
96+
现代C++使用成员初始化列表,而不是直接初始化列表。具体是:
97+
98+
```cpp
99+
class Foo{
100+
int m_a{};
101+
int m_b{};
102+
103+
Foo(int a, int b) : m_a{a}, m_b{b} {
104+
//other...
105+
}
106+
}
107+
```
108+
109+
以前(C++03)之前则是用的`()`直接初始化。
110+
111+
成员初始化的顺序和成员初始化列表无关,只跟泪中定义成员变量的顺序有关。
112+
113+
### `std::string_view`特殊处理
114+
115+
一个例子:
116+
117+
```cpp
118+
#include <iostream>
119+
#include <string>
120+
#include <string_view>
121+
122+
class Ball
123+
{
124+
private:
125+
std::string m_color { "none" };
126+
double m_radius { 0.0 };
127+
128+
public:
129+
Ball(std::string_view color, double radius)
130+
: m_color { color }
131+
, m_radius { radius }
132+
{
133+
}
134+
135+
const std::string& getColor() const { return m_color; }
136+
double getRadius() const { return m_radius; }
137+
};
138+
139+
void print(const Ball& ball)
140+
{
141+
std::cout << "Ball(" << ball.getColor() << ", " << ball.getRadius() << ")\n";
142+
}
143+
144+
int main()
145+
{
146+
Ball blue { "blue", 10.0 };
147+
print(blue);
148+
149+
Ball red { "red", 12.0 };
150+
print(red);
151+
152+
return 0;
153+
}
154+
```
155+
156+
> 为什么这里构造函数需要用`string_view`作为参数?不能用`const string&`来替换?
157+
158+
`string_view`提供了灵活性,如果选择后者,那么如果传入一个C语言的字面量字符串的时候,就必须在堆上构建临时的`string`对象,而这对性能开销很大;对于前者,永远不会构造临时对象,而是只有一个指针,在真正初始化的时候完成一次复制。(甚至后面还能用移动语义)
159+
160+
> 为什么`getter`不能像上面一样反过来?
161+
162+
因为在类内部的存储对象就是真正的`string`,给出它的引用使得外部访问的类型明确,不会造成歧义;同时也提示这个引用的生命周期是明确的————跟成员变量一致。

0 commit comments

Comments
 (0)