1. core language features
1.1. C99 preprocessor
C99的预处理器宏可以支持一些复杂的操作,VS2015支持部分特性,VS2019支持更多。很多大型C项目,像CPython、ffmpeg等,需要支持C99,所以需要使用VS2019编译。C++程序员,一般少用宏,尤其是复杂的宏。
1.2. static_assert
执行编译时的断言检测,提前发现问题,降低Bug修复成本。VS2010及之后的版本支持此特性。
C++11中的static_assert是一种编译时断言,它允许程序员检查模板参数或其他编译时常量的属性。如果条件失败,它会停止编译并生成一个编译器错误信息。它的语法是 static_assert(condition, message)
static_assert((sizeof(var) >= 4), "Error");
1.3. Right angle brackets
typedef std::vectorstd::vector Flags;C++11之前,右边的>>需要空格才可以。
在C++11中,右尖括号(>
)可以用于表示模板参数,而无需在它们之间添加空格。这被称为“右边角括号”问题,其中编译器会将两个连续的尖括号(>>
)解释为右移运算符,而不是模板参数的关闭尖括号对。
例如,您可以使用以下语法:
std::vector<std::vector<int>>
而不是以下语法:
std::vector<std::vector<int> >
这使代码更易于阅读,并避免了由双尖括号的歧义可能引起的错误。
VS2005及之后的版本支持此特性。
1.4. Extended friend declarations
C++11引入了扩展友元声明(Extended friend declarations)的新特性,可以更加灵活地定义友元。VS2013及之后的版本支持此特性。示例如下:
class C;
typedef C Ct;
class X1 {
friend C; // OK: class C is a friend
};
class X2 {
friend Ct; // OK: class C is a friend
friend D; // error: no type-name D in scope
friend class D; // OK: elaborated-type-specifier declares new class
};
1.5. long long
long long占用8个字节(64位),可以表示的整数范围是从-9,223,372,036,854,775,808到9,223,372,036,854,775,807。VS2005及之后的版本支持此特性。
1.6. Compiler support for type traits
可以用来判断类型状态,有**has_virtual_destructor、**is_base_of等函数。VS2015及之后的版本支持此特性。
// has_virtual_destructor.cpp
#include <stdio.h>
struct S {
virtual ~S() {}
};
int main() {
__has_virtual_destructor(S) == true ?
printf("true\n") : printf("false\n");
}
// is_base_of.cpp
#include <stdio.h>
struct S {};
struct T : public S {};
int main() {
__is_base_of(S, T) == true ?
printf("true\n") : printf("false\n");
__is_base_of(S, S) == true ?
printf("true\n") : printf("false\n");
}
1.7. auto
原先用于声明自动变量的功能被废除,新功能为修改变为通过变量的初始化值来推导出变量的类型。
VS2010及之后的版本支持此特性。新功能简单示例:
auto x = 5; // ok, x has type int
const auto *v = &x, u = 6; // ok, v has type const int*, u has type const int
static auto y = 0.0; // ok, y has type double
static auto int z; // ill−formed, auto and static conflict
auto int r; // ok, r has type int
1.8. Delegating constructors
类可能有很多构造函数,有时一个构造函数的功能其实是在另一个构造函数的功能之上再添加一点新的功能。
传统的方法下,如果想共用相同的代码,必须将相同代码抽象为一个函数,然后再共用。VS2013及之后的版本支持此特性。
有没有更方便的方法呢?C++11中提出的委托构造函数,可以实现相关功能。
class Foo
{
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char, int)
};
1.9. extern template
extern template 是 C11 中的一个特性,用于显式实例化模板。在 C 中,模板可以提供泛型编程支持,但在不同的编译单元中,对同一个模板进行实例化会带来一些问题,例如代码膨胀和编译时间增加等。VS2010及之后的版本支持此特性。
为了解决这个问题,C++11 引入了 extern template 关键字,它允许将模板的实例化推迟到其他编译单元中。具体来说,使用 extern template 可以将模板实例化放在一个编译单元中,并在其他编译单元中使用 extern template 声明来避免重复实例化。
以下是一个示例代码:
// test.h
template <typename T>
class Test {
public:
void func();
};
// test.cpp
#include "test.h"
template <typename T>
void Test<T>::func() {
// Implementation here...
}
template class Test<int>;
template class Test<double>;
// main.cpp
#include "test.h"
extern template class Test<int>;
int main() {
Test<int> t;
t.func();
return 0;
}
在上述示例代码中,我们首先定义了一个名为 Test 的类模板,在 test.cpp 文件中实例化了该模板,并在 main.cpp 文件中使用 extern template 关键字声明了 Test 的实例化。这样做可以避免在 main.cpp 编译时再次实例化 Test,从而加速编译过程并减少代码膨胀。
1.10. constexpr
constexpr是C++11中新引入的指示符,允许函数和变量在编译时计算出值,可以大幅提升代码性能。例如,斐波那契数列的计算,可以直接在编译时计算出来。如下图,factorial函数直接被编译为表格,直接查表获取。VS2015及之后的版本支持此特性。
1.11. Template aliases
C++11引入了模板别名(Template aliases)功能,可以使用using关键字来定义一个模板别名。它允许程序员为现有的类型或模板起一个新的名称,以方便使用和提高代码的可读性。VS2013及之后的版本支持此特性。
以下是一个示例代码:
template<typename T>
using Vec = std::vector<T>; // 定义一个模板别名Vec,表示std::vector<T>
int main()
{
Vec<int> v{1, 2, 3}; // 使用Vec作为std::vector<int>的别名
for (auto i : v)
std::cout << i << ' ';
}
1.12. char16_t and char32_t
C++11引入了两个新的字符类型:char16_t和char32_t。它们分别用于表示16位和32位的Unicode字符,以支持国际化和本地化应用程序开发。VS2015及之后的版本支持此特性。
char16_t表示一个16位的Unicode字符,类似于wchar_t,但是其大小是固定的。可以使用u前缀来表示一个char16_t字符常量,例如:
char16_t c = u'中';
char32_t表示一个32位的Unicode字符,也可以使用U前缀来表示一个char32_t字符常量,例如:
char32_t c = U'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)