您正在查看: 标签 C++ 下的文章

C++ 字符编码转换方法

与平台相关的方法

Win32

使用 WideCharToMultiByteMultiByteToWideChar

Apple

使用CFStringCreateWithBytes

linux

使用iconv库

Continue Reading...

C++ cout wcout 无法输出与locale的关系

 C++标准为C++标准IO库设计了十分完善的国际化文本处理机制。但在实际使用中,却发现各种编译器对它的支持性存在较大的差异,很多时候无法正确的输出字符。于是我对此进行了深入的调查。

Continue Reading...

C++ 坑笔记

返回值优化

以前我们可能会认为C++的复制构造函数会在函数返回时调用,但是现代的编译器对返回值有优化。
wiki上有详细的原文

#include <iostream>

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
  return 0;
}

宏函数可能引发的错误

#define DO_MAX(a,b) f((a) > (b)? (a):(b))
int a = 5, b = 0;
DO_MAX(++a, b);      //a被累加二次
DO_MAX(++a, b+10);   //a被累加一次

可以采用inline模板,照样可以达到宏一样的性能。而且没有这种宏替换带来的缺点,而且有类型检查。

template<typename T>
inline void DO_MAX(const T& x, const T& b) {
    f(a > b ? a : b);
}

对于单纯的常量,最好使用const或者enums,替换#define
对于宏函数,最好改用inline

const 尽可能的使用const

  • const修饰常量
  • const修饰指针本身
  • const修饰成员函数
    表示该成员不会改变类的成员,如果需要改变的某个变量的话,使用mutable修饰成员
    const修饰成员函数时仅仅只是测试该函数执行过程中有没有进行修改或者赋值。如果故意把某个变量的引用返回出去,也可能会被外部修改。
    在const和non-const的成员函数中避免重复,如果需要,通过const_cast进行转换。
  • const修饰函数形参

对象初始化

C++11之前对象初始化不具有线程安全特性
C++的初始化成员次序非常固定,基类早于子类的初始化。析构时,正好相反

C++中对定义于不同编译单元内的全局静态对象的初始化顺序不确定。但是都是在main函数之前。 编译单元其实就是单个cpp文件。 最常见而且容易被忽略的情况是 non local static的模板类成员。模板类在被使用时编译才具体化。
C++中的local static对象一定会在第一次使用时定义。

A * getInstance() {
   static A * m;
   if (m == nullptr) {
      Lock();
      m = new A();
      UnLock();
   }
   return A;
}  //这段代码在c++11之前 线程不安全

void test() {
   cout << "before a";
   static A a();           //假设a构造是输出 I am created.
   cout << "after a";     
} // 这段代码的输出结果是, 先before,再I am created,再after

C++的默默编写的函数

  • 构造函数
  • 析构函数
  • 复制构造函数
  • 赋值重载

若不想使用编译器自动生成的函数,就要明确拒绝

C++11中 使用 delete 可以删除默认的函数
之前的版本,可以显式声明,并且设置为private。不需要实现。

多态基类的析构函数声明为virtual

否则对指向子类的基类指针使用delete时候,会产生内存泄露。

C++Primer第五版-学习笔记-类

构造函数

(合成的)默认构造函数

当一个类没有定义任何构造函数的时候,编译器会为其生成默认构造函数,又被称为合成的构造函数。
类的默认构造函数要求,类的成员类必须有空参数的构造函数。

Continue Reading...

C++Primer第五版-学习笔记-数据定义,过程控制,函数

直接初始化和拷贝初始化

如果使用=来初始化一个变量,实际上执行的是拷贝初始化。编译器把等号右边的初始值拷贝到新创建的对象中去。 如果不使用等号,则执行的是直接初始化

Continue Reading...