11.12.10

我最崇拜的人姓刘

所有内容摘自互联网,感谢各位网友的原创!持续更新中;)

我最崇拜的人姓刘,他获得过国际大奖,他的所作所为激发了国人的斗志,虽然有一段时间他从我们眼前消失了,但是我相信他的精神永存。他的名字叫刘翔。

我最崇拜的人姓刘,他领导过学生闹学运,出过书,得过外国的奖,后来被冤枉做了很多年牢。但我相信,这些都是历史给他的考验,因为他说过,好在历史是人民写的。他的名字是刘少奇。

我最崇拜的人姓刘。他是个博士,他出过书、当过被告。得过西方很多国家的大奖,以及香港台湾等境外组织颁发的奖。他是很多中国人的偶像,他是中国人的自豪和骄傲。他叫刘德华!

我最崇拜的人姓刘,ta面对暴力无所畏惧,坚定信仰自己的理念。尽管ta早早地被强权迫害,但ta的名字直到今天仍在流传。ta是刘胡兰。

我最崇拜的人姓刘,出过书,获得过国际大奖,用多年的拼搏和追求向世界展示国人的无悔青春,虽然有一段时间住过牢,但是我相信特不会为此而向命运屈服。特的名字是刘晓庆。

我最崇拜的人姓刘,他获得了世界性的奖项,因为他的推手技惊全球以至于不得不说:我没有敌人。有时候面对记者会结结巴巴,他一度消失在人们的视野。整个世界都经常默念他的名字:国家的未来栋梁!他的名字叫刘国梁。

我最崇拜的人姓刘,他十几年如一日,忍辱负重,勤奋耕耘,从一个东北土鳖成长为亿万人瞩目的理性楷模。他致力于一个理想化的行动,让自己备受磨难,但人们心里为他树起了一座丰碑,他的名字叫刘老根儿。

我最崇拜的人他姓刘,他一生传奇,80年代就名扬国际,热衷挑战强拳,获得过无数国际大奖。他的一生没有敌人。他就是拳王刘易斯。

我崇拜的人姓刘,从80年代开始就写出了一系列传世佳作,在一代又一代爱好自由的人手中传颂。尽管关于他的作品有一些争议,但好无偏见的说他的文字影响和改变了很多推友。他就是刘欣慈。

我最崇拜的人姓刘,他获得过很多境外组织的奖杯,他的作品流行海内外,他忠厚的面貌总是让人感到亲切,他也很关心缅甸昂山阿姨的情况,他的名字叫刘青云。

我最崇拜的人姓刘,他以人性化的实践,经历和见证了封建小农经济下个人良心的最大发挥。他清白而廉洁,但却历经诬陷,一个好人被钉在耻辱里,体现了专制政权的强横与无耻。然而,他被人传颂为良知的化身和尊严的维护者。他的名字叫刘文彩。

我不崇拜的人姓刘,他某年因为因为被央视现场报道使用幕后黑手欺骗全国人民而一举闻名。他荣获过那个领域的国际大奖,他的成就可以说在中国没有敌人。网上关于他的争议一直很多,不过丝毫不影响他的影响力。他就魔术师刘谦。

我最崇拜的人姓刘,ta是一个东北人,ta于1989年春夏之交正式登上历史舞台,ta在世界上拥有极高的声望,ta就是我国著名游泳运动员刘子歌。

我最崇拜的人姓刘,他为了反抗强权暴政忍辱负重,尽管他有很多先天缺陷,但是仍然不能阻止他成为时代的领袖,他的名字刘邦。

我最崇拜的人姓刘,虽然我没有见过他,但他一直为大家的幸福生活在默默的努力。现在越来越多的人知道他喜欢他的作品,甚至还有人盗版他的东西冒充来卖,这是一件好事,他叫刘一手。

我最崇拜的人姓刘,Ta和Ta的同志们为了自由和人权与专制进行了不懈的斗争,Ta用自身惨痛的牺牲证明了专制的残暴,人们铭记着Ta的事迹,专制却从学校课本里把Ta的名字拿走,Ta的名字叫刘和珍。

我最崇拜的人姓刘,每当我觉得社会太黑暗、生活得太辛苦要放弃时,脑海中出现ta的身影又让我重燃斗志。ta是刘亦菲。

我最崇拜的人姓刘。念过大学,刚正不阿,曾被当权者剥夺工作,中年后又被关入监狱。每个中国人都应该记住他的名字。他叫刘墉!

我最崇拜的人姓刘,ta很早就被黑恶势力打压,登上封面,影响很坏,因此消失了很长时间,但是最近ta又出来了,还获得了很多奖项,跟影帝结合了,ta叫刘嘉玲。

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

7.12.10

The Beauty of Qt 3: Implicit Sharing

To maximize resource usage and minimize copying, Qt uses implicit data sharing in many classes, so that the data is copied only when a function writes to it. This trick is also referred to as flyweight pattern sometimes.

Now let's take QByteArray as an example to see how it's implemented. It uses a private struct of Data to track the shared data:
struct Data {
  QBasicAtomicInt ref; // reference count, the operation on it is atomic
  int alloc; // allocated space for the data
  int size; // actual size of the data, not counting the ending '\0' added by QByteArray
  char *data; // point to the data
  char array[1]; // where the data is stored, and the data always end with '\0'
};


Here, we use both the pointer of data and array just because the data might actually be stored in another object. When an object is copied, e.g. through the assignment operator, it only copies the pointer to the shared data:
QByteArray &QByteArray::operator=(const QByteArray & other)
{
  // increase the reference count of the shared data it's supposed to be used
  other.d->ref.ref();

  // decrease the reference count of the share data currently used, and free it if no one else is using
  if (!d->ref.deref())
    qFree(d);

  // point to the shared data
  d = other.d;

  return *this;
}


On the other hand, if it's to be changed by e.g. the resize() function, it copies the data if any other object also shares it:
void QByteArray::resize(int size)
{
  if (size <= 0) {
    // if the target is no bigger than 0, points to an empty data block
    Data *x = &shared_empty;
    x->ref.ref();
    if (!d->ref.deref())
      qFree(d);
    d = x;
  } else if (d == &shared_null) {
    // if currently a null array, just create a new data block
    Data *x = static_cast<data *>(qMalloc(sizeof(Data)+size));
    Q_CHECK_PTR(x);
    x->ref = 1;
    x->alloc = x->size = size;
    x->data = x->array;
    x->array[size] = '\0';
    (void) d->ref.deref();
    d = x;
  } else {
    // if any other object uses this data block, or the current memory is too small or too big
    // reallocate space, and copy the data for it
    // note that this operation might consume some time if the data is huge
    if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))
      realloc(qAllocMore(size, sizeof(Data)));
    if (d->alloc >= size) {
      d->size = size;
      if (d->data == d->array) {
        d->array[size] = '\0';
      }
    }
  }
}


With this in mind, let's see how to use QSharedData and QSharedDataPointer to implement our own implicit shared data objects.
// first implement your data object inheriting from QSharedData, which provides the reference count
class SharedData: public QSharedData
{
public:
  SharedData()
    : QSharedData()
    , var(0)
  {}

  SharedData(const SharedData &other)
    : QSharedData(other)
    , var(other.var)
  {}

  int var;
};

// then the data owner
class DataOwner
{
public:
  DataOwner()
  : d(new SharedData)
  {}

  DataOwner(int var)
  : d(new SharedData)
  {
    // for write access, the -> operator will automatically copy the shared data if needed
    d->var = var;
  }

private:
  // this template class hides all the details for implicit sharing
  // therefore, no need to provide copy constructor or assignment operator
  QSharedDataPointer<SharedData> d;
};


Quite simple, right ;) Then just proceed to implement explicit shared data objects using QExplicitlySharedDataPointer yourself.

Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!

1.12.10

The Beauty of Qt 2: Meta Object

Besides the D-pointers, another interesting thing in Qt is the Q_OBJECT macro. It provides the access to meta objects, which enables you to enjoy more features of a QObject, e.g. signals and slots. The meta object provides information about class name, properties and methods of a QObject, which is also known as reflection.

Using QMetaObject, you can print the information of the class name, etc.:
QObject obj;
const QMetaObject *metaObj = obj.metaObject();
qDebug() << "class name: " << metaObj->className();
qDebug() << "class info count: " << metaObj->classInfoCount();
qDebug() << "methods: ";
// starting from QMetaObject::methodOffset() so it won't display the methods inherited
for (int i = metaObj->methodOffset(); i < metaObj->methodCount(); ++i)
  qDebug() << metaObj->method(i).methodType() << " " << metaObj->method(i).signature();


As none of these information is supported in pure C++, Qt uses the Meta Object Compiler (moc) to do all the tricks. It reads each header file, and generates a C++ source file (moc_*.cpp) containing the code for meta-object, if it finds a Q_OBJECT macro used in any class declaration. With the code generation approach, Qt not only gains the flexibility as in e.g. Java, but also keeps the performance and scalability as in C++.

Suppose we have the following simple class:
class MyObject : public QObject
{
  Q_OBJECT
public:
  explicit MyObject(QObject *parent = 0);

  void myFunc();

public slots:
  void mySlot(int myParam);

signals:
  void mySignal(int myParam);
};


The following code / information will be generated by moc, and can be retrieved through pointers defined in the anonymous struct of QMetaObject::d:
// pointed by QMetaObject::d.data, the beginning stored "as" a QMetaObjectPrivate struct
static const uint qt_meta_data_MyObject[] = {
  5, // revision, the internals have been changed several times
  0, // classname, offset of qt_meta_stringdata_MyObject

  // the following are defined as (number, index) pair
  0, 0, // classinfo
  2, 14, // we have two methods, starting at index 14 (i.e. the signal)
  0, 0, // properties
  0, 0, // enums/sets
  0, 0, // constructors

  0, // flags
  1, // signal counts

  // for signals slots, and properties, the signatures and parameters are offset of qt_meta_stringdata_MyObject
  // signals: signature, parameters, type, tag, flags
  18, 10, 9, 9, 0x05,

  // slots: signature, parameters, type, tag, flags
  32, 10, 9, 9, 0x0a,

  0 // eod
};

// pointed by QMetaObject::d.stringdata
static const char qt_meta_stringdata_MyObject[] = {
  "MyObject\0\0myParam\0mySignal(int)\0"
  "mySlot(int)\0"
};


The above information, as well as the information for its base class, is stored as the static meta object for this class:
const QMetaObject MyObject::staticMetaObject = {
  { &QObject::staticMetaObject, // pointer to its base class, stored at QMetaObject::d.superdata
    qt_meta_stringdata_MyObject, qt_meta_data_MyObject, 0 }
};


In this way, if you want to do type cast for QObject, instead of using the somewhat expensive operator of dynamic_cast, we can use qobject_cast. It exploits the benefits of the meta object system, thus avoiding the runtime type cast:
template <class T> inline T qobject_cast(QObject *object)
{
#if !defined(QT_NO_QOBJECT_CHECK)
  reinterpret_cast(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast(object));
#endif
  return static_cast(reinterpret_cast(0)->staticMetaObject.cast(object));
}


Here, the trick is that the QMetaObject of the target type checks if the object inherits from it:
const QObject *QMetaObject::cast(const QObject *obj) const
{
  if (obj) {
    const QMetaObject *m = obj->metaObject();
    do {
      if (m == this)
        return obj;
    } while ((m = m->d.superdata));
  }
  return 0;
}


Also, moc will generate some code for each signal. Whenever a signal is emitted, this function will be called internally:
void MyObject::mySignal(int _t1)
{
  void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
  // it checks all the connected slots, and call each of them based on the connection type
  QMetaObject::activate(this, &staticMetaObject, 0, _a);
}


In the end, the slots are invoked by the generated qt_metacall function:
int MyObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
  // if this function is called by the super class, just return
  _id = QObject::qt_metacall(_c, _id, _a);
  if (_id < 0)
    return _id;

  // call the function based on its ID
  if (_c == QMetaObject::InvokeMetaMethod) {
    switch (_id) {
    case 0: mySignal((*reinterpret_cast< int(*)>(_a[1]))); break;
    case 1: mySlot((*reinterpret_cast< int(*)>(_a[1]))); break;
    default: ;
    }

    // remove the IDs "consumed" by this class so that in its subclass the ID always starts with 0, and the return value of -1 means already consumed
    _id -= 2;
  }

  return _id;
}


Buzz Delicious Digg it! Facebook Reddit Stumbleupon Technorati Tweet it!