const 语义的必要性

阅读层面

void foo(Data* data);
void bar(const Data* data);

对于 foo,可能其实现中并不会修改 data 的内容,但是调用者无法知道这一点,因此调用 foo 时,需要考虑 data 的内容是否会被修改。即使查看过 foo 的实现,并不会实际修改 data 的内容,但是 foo 的实现可能会在后续发生变化,而调用者无法感知这一点。因此调用 foo 时,始终存在潜在的风险,每次使用 foo 时,都需要重新检查 foo 的实现,以确保 data 的内容不会被修改。

对于 bar,调用者可以放心地传递 data 的地址,因为 bar 保证不会修改 data 的内容。即使 bar 的实现发生变化,只要 const 限定符不被移除,调用者就不需要关心 bar 的实现细节。

调用开销层面

void foo(QByteArray& ba)
{
    const char* data = ba.data();
    for (int i = 0; i < ba.size(); i++) {
        int a = data[0];
        int b = data[1];
        int c = data[2];
        // do something...
    }
}

QByteArray 的部分实现如下(有所精简):

inline char QByteArray::at(int i) const { return d->data()[i]; }

inline char QByteArray::operator[](int i) const { return d->data()[i]; }

inline char *QByteArray::data() { detach(); return d->data(); }

inline const char *QByteArray::data() const { return d->data(); }

inline const char *QByteArray::constData() const { return d->data(); }

inline void QByteArray::detach() {
    if (d->ref.isShared() || (d->offset != sizeof(QByteArrayData)))
        reallocData(uint(d->size) + 1u, d->detachFlags());
}

首先得到如下结论:

  • char *QByteArray::data() 会调用 QByteArray::detachQByteArray::detach 会调用 QByteArray::reallocData 申请空间,存在额外开销。
  • QByteArray::constData() 不存在额外开销。

由此得到优化方案一
ba.data() 改为 ba.constData(),可以避免 QByteArray::detach 的调用,减少额外开销。

void foo(const QByteArray& ba)
{
    const char* data = ba.constData();
    for (int i = 0; i < ba.size(); i++) {
        int a = data[0];
        int b = data[1];
        int c = data[2];
        // do something...
    }
}

继续观察,发现结论:

  • foo 不需要修改 ba 的内容,仅需要读取 ba 的内容,因此 data 的类型是 const char*
  • const char *QByteArray::data() const 也不会调用 QByteArray::detach,不存在额外开销。

如何才能调用 const char *QByteArray::data() const 而不是 char *QByteArray::data() 呢?可以将 foo 的参数改为 const QByteArray& ba,这样 ba.data() 就会调用 const char *QByteArray::data() const,而不是 char *QByteArray::data()

由此得到优化方案二
foo 的参数改为 const QByteArray& ba,可以避免 QByteArray::detach 的调用,减少额外开销。

void foo(const QByteArray& ba)
{
    const char* data = ba.data();
    for (int i = 0; i < ba.size(); i++) {
        int a = data[0];
        int b = data[1];
        int c = data[2];
        // do something...
    }
}

继续观察,发现:

  • data 的作用仅仅是为了使用 [],调用者似乎不知道 QByteArray::operator[] 的存在。

由此得到优化方案三
移除 data,直接使用 ba[index]

void foo(const QByteArray& ba)
{
    for (int i = 0; i < ba.size(); i++) {
        int a = ba[0];
        int b = ba[1];
        int c = ba[2];
        // do something...
    }
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值