您当前位置: 首页 »

编码技巧

分类目录归档: 编码技巧 - 第3页

一个类在被编译器处理以后包含的数据结构

class A

{

public:

}

一般对于使用者来说这个类只有1个数据结构,那就是类本身。

实际上,一个类包含了3个数据结构。

除了类本身以外,还包含了一个函数表、和指向函数表的指针。

函数表是用来保存虚函数在本类中的中的具体实现地址的。

而指向函数表的指针,值用于表示某个虚函数在函数表的地址。

2013-10-12 | | 编码技巧

一个类在被编译器处理以后包含的数据结构已关闭评论

不给函数做对象的值传递另一个重要原因

在调用函数时,一般都不建议采用值传递,原因是因为要建立一个临时的拷贝;这样会带来空间和时间复杂度的提升。

一般除非很特殊情况,很少把对象以值的方式进行传递到函数里面。

实际上,不讲对象做值传递还有一个比较重要的原因。

在C++的多态中,如果父类的指针指向了一个子类对象,并对该对象做值传递,会导致子类数据丢失。大致代码如下:


class CA

{

};

class CB : public CA

{

};

 

void func(CA src);

 

int main()

{

CA* p1 = new CB;

func(*p1);

....

}

在这个代码里,实际上调用func时,使用了CA的默认拷贝构造函数,因为对于CB的所有数据就丢失了,在func里面的临时对象也仅仅是CA类型。

2013-10-11 | | 编码技巧

不给函数做对象的值传递另一个重要原因已关闭评论

++重载符

首先说一下++重载符,++分为前后两种方式的调用。因此就有了两种的符号的调用。大致如下(对于后置++的做法采用了不严谨的重载,返回的应该是 const对象)

namespace class_cplusplus10
{
class CBase
{
public:
CBase& operator++()        //这里是前置++调用
{
printf(_T("class_cplusplus10::CBase& operator++()\n"));
return *this;
}
CBase& operator++(int)     //这里是后置++调用
{
printf(_T("class_cplusplus10::CBase& operator++(int)\n"));
return *this;
}

CBase& operator--()
{
printf(_T("class_cplusplus10::CBase& operator--()\n"));
return *this;
}
CBase& operator--(int)
{
printf(_T("class_cplusplus10::CBase& operator--(int)\n"));
return *this;
}
};

}

上面的代码已经很好的说明了哪一些是前置调用重载,哪一些是后置调用的重载。

然后通过这些函数可以来看看一些哗众取宠的笔试题。

class_cplusplus10::CBase base;
++base++;

问++base++的调用是怎样的,通过调试发现,实际上后置++是先被调用,然后前置++。

不过这里是c++,而这种笔试题往往考的是操作符的优先级。也许一个对象和一个内置类型的变量存在一些不同

2013-10-10 | | 编码技巧

++重载符已关闭评论

[chromium]MessageLoop控制所谓的“消息嵌套”问题

所谓的消息嵌套,说白了,就类似函数递归。下面存在这样一种场景,会导致所谓的嵌套发生。

需要解决一种使用场景,例如主线程post一个任务到MessageLoop的队列中,然后调用MessageLoop::Run
这是进入消息处理,而这个抛入的任务实际上做的也是调用MessageLoop::Run
那这就陷入了2个问题
1,要么出现多次“嵌套”,直到最后一个待处理的任务被执行完,然后再逐级返回,以至于最后一个任务被处理完。
2,要么直接死循环或者说是饿死。因为有可能抛入的任务都是调用同一个线程的MessageLoop::Run,然后最后被处理的任务被停在了事件等待上面,这个事件是用于等待有新MessageLoop任务抛入的。

因此nestable_tasks_allowed_ 标记就成了关键,这个标记控制着不允许任务会被嵌套的情况发生。

2013-06-04 | | win, 编码技巧

[chromium]MessageLoop控制所谓的“消息嵌套”问题已关闭评论

[chromium]MessageLoopProxyTest单元测试中的一个隐蔽问题

代码如下

  MessageLoop* task_run_on = NULL;
  MessageLoop* task_deleted_on = NULL;
  int task_delete_order = -1;
  MessageLoop* reply_run_on = NULL;
  MessageLoop* reply_deleted_on = NULL;
  int reply_delete_order = -1;

  scoped_refptr task_recoder =
      new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
  scoped_refptr reply_recoder =
      new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);

  ASSERT_TRUE(task_thread_.message_loop_proxy()->PostTaskAndReply(
      FROM_HERE,
      Bind(&RecordLoop, task_recoder),
      Bind(&RecordLoopAndQuit, reply_recoder)));

  // Die if base::Bind doesn't retain a reference to the recorders.
  task_recoder = NULL;
  reply_recoder = NULL;
  ASSERT_FALSE(task_deleted_on);
  ASSERT_FALSE(reply_deleted_on);

  //--- 这里将是比较关键的一个问题 begin ---
  UnblockTaskThread();
  current_loop_->Run();
  //--- 这里将是比较关键的一个问题 end ---

  EXPECT_EQ(task_thread_.message_loop(), task_run_on);
  EXPECT_EQ(current_loop_.get(), task_deleted_on);
  EXPECT_EQ(current_loop_.get(), reply_run_on);
  EXPECT_EQ(current_loop_.get(), reply_deleted_on);
  EXPECT_LT(task_delete_order, reply_delete_order);

readmore

2013-06-04 | | win, 编码技巧

[chromium]MessageLoopProxyTest单元测试中的一个隐蔽问题已关闭评论

【编码技巧-win】关于字节编码长度在windows里面的处理

win 2k时代开始,微软用的中文系统编码均是unicode,而unicode编码被微软使用固定的2个字节来存放(也许这就是和unicode字符集的编码长度有关)。

因此,在中文windows平台中可以直接等同这么看

unicode便编译的代码,并且和unicode版本的微软库打交道的代码。在判断字符串时是否含有中文时,只要循环遍历字符串中的每一个字节,判断对应的 uint8 是否 大于 0x7F。如果大于,说明有中文一类的,非ascii字符。将对应的字符串buff,转换成wchar即可。否则直接按照char方式来用即可

 

2013-04-08 | | win, 编码技巧

【编码技巧-win】关于字节编码长度在windows里面的处理已关闭评论