0%

auto / decltype in C++11

auto

雖然在C語言的時候就有auto關鍵字了,不過現在已經很少使用。
C++11重新給予auto新的語意。可以在編譯的時候進行型別推導,因此你可以這樣寫

1
2
int i = 0;
auto j = 0;

不過用在這裡太大材小用了,可能簡單的東西變得更難看懂。通常都是這麼使用

1
2
3
vector<int> vec;
vector<int>::iterator it1 = vec.begin();
auto it2 = vec.begin();

使用auot的寫法更容易看懂,當vec的型別要從int改成double時,it1的型別需要修改,而it2則是編譯器幫我們推導,少了可能的錯誤。
C++11又新增了一種Reutrn Value Syntax
原本的函數寫成

1
int add2(int a, int b);

現在可以寫成

1
uto add2(int a, int b) -> int;

看了別人的分析之後,我才發現這樣寫的好處。
假設我們現在有個類別Person

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person {
public:
enum PersonType {
Child,
Adult,
Senior
};
void SetPersonType(PersonType t);
PersonType GetPersonType();
private:
PersonType type_;
};
void Person::SetPersonType(PersonType t) {
type_ = t;
}
PersonType Person::GetPersonType() {
return type_;
}

GetPersonType會編譯不過,因為外界不知道PersonType是什麼,必須改成這樣

1
2
3
Person::PersonType Person::GetPersonType() {
return type_;
}

當然,改成這樣就不用這麼麻煩了

1
2
3
auto Person::GetPersonType() -> PersonType {
return type_;
}

有了decltype之後,城市就能這樣寫了

1
2
3
4
5
6
7
8
template <typename Builder>
auto
makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )
{
auto val = builder.makeObject();
// do stuff with val
return val;
}

新的Return Value Syntax也應用在Lambda Expression上,有機會再說吧。

decltype

decltype跟auto算是一體的兩面,auto是可以用來宣告指定類型的變數,而decltype是得到某個變數的類別。

1
2
int i = 0;
decltype(i) j = i; // auto j = i;

auto兩三事

auto裡面還是有些陷阱,對referencepointer的行為不同。
看看以下的code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
tatic int foov = 0;
static int barv = 1000;
void showfoo()
{
cout << "foo's value = " << foov << endl;
}
void showbar()
{
cout << "bar's value = " << barv << endl;
}
int& foo()
{
return foov;
}
int* bar()
{
return &barv;
}
int main()
{
showfoo();
auto v1 = foo();
v1 = 1;
showfoo();
auto& v2 = foo();
v2 = 2;
showfoo();
showbar();
auto p1 = bar();
*p1 = 1001;
showbar();
auto *p2 = bar();
*p2 = 1002;
showbar();
}

執行結果如下

1
2
3
4
5
6
foo's value = 0
foo's value = 0
foo's value = 2
bar's value = 1000
bar's value = 1001
bar's value = 1002

可以看到auto在對reference的時候預設是Value Type,必須手動加上&才能拿到Reference。而Pointer就一視同仁。
看起來還真不協調 _