c++11 最反直觉的地方

2014-11-24 09:02:56 · 作者: · 浏览: 1

1 auto 会自动把 引用 去除掉

int& get();
auto k = get(); // k的类型是int,而不是int&

Derived object;
auto& same_object = (Base&)object;
auto another_object = (Base&)object; //会重新构造个Base对象


2 decltype 有时会自动把 引用 加上

int x;
decltype((x)) 和 decltype(*&x) 的类型是int&,而不是int

在宏中使用decltype时,要特别注意别多加了括号。

下面这段代码错在哪里?
template
auto min(T t, R r) -> decltype(t < r t : r)
{
return (t < r t : r);
}

decltype(t < r t : r)的类型是T&或R&,而不是所希望的T或R!


标准是这样规定的:

The type denoted by decltype(e) is defined as follows:
— if e is an unparenthesized id-expression or an unparenthesized class member
access (5.2.5), decltype(e) is the type of the entity named by e. If there
is no such entity, or if e names a set of overloaded functions, the program
is ill-formed;
— otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;
— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
— otherwise, decltype(e) is the type of e.

3 std::move、std::forward、右值引用

C++11 引入 右值引用,可以做到:函数转发、针对临时对象优化
move是动词,从字面上理解好像是要移动对象,其实std::move只是简单的将类型转成右值引用而已!!! 可以理解成 cast_to_rvalue_reference 或 treat_as_temporal_object。

void test1(int&&) {}

void test2(int&& value) //注意:value的类型是int,而不是int&&
{
test1(value); //无法编译通过,因为value的类型是int! 必须转换类型
test1(static_cast(value)); //或者
test1(std::forward(value));
}

test2函数中,value的类型是int,而不是int&&。
这是一个不得已的选择。如果value的类型是int&&的话,就会有副作用:

void increase(int& value) { ++value; }
void test3(int&& value) { increase(value); }

char ch = 'a';
test3(ch); //本意是改变ch值,但实际上ch值不会改变,改变的是临时对像
通过转发函数test3,increase函数可以修改临时对像,
这造成程序员犯的错误(如上面的例子),难以在编译时就被找出来。


std::forward(value) 等价于 static_cast(value),感觉后者更容易理解。
std::forward 起到的转发作用。如果T类型为 R&、 R&&,经过类型转换后,其类型还是和原来的一样。
C++11中 www.2cto.com
R& & 等同于 R& (在c++03中,R& &这种写法是非法的)
R&& & 等同于 R&
R& && 等同于 R&
R&& && 等同于 R&&