跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 在使用某些类库的时候,有时传引用,有时传指针,这有什么设计原则吗?
未分類
5 2 月 2021

在使用某些类库的时候,有时传引用,有时传指针,这有什么设计原则吗?

在使用某些类库的时候,有时传引用,有时传指针,这有什么设计原则吗?

資深大佬 : James369 6

比如说,这 2 个 Http 的 post 方法:
QNetworkReply *post(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
一个 data 传指针,一个传引用。

另外,我发现一个有趣现象,就是使用栈上的变量,最好传引用,传指针可能会导致运行出错。
比如像这样:
QIODevice dev;
… //dev 操作
auto reply = manager->post(request, &dev); //栈上的 dev 会出现段错误,而如果是 new QIODevice 再传指针就没事。

而这种情况,直接用栈上的变量却又没事。
QByteArray data;
… //data 操作
auto reply = manager->post(request, data); //一切正常

大佬有話說 (21)

  • 主 資深大佬 : James369

    另外,顺便问下怎么贴漂亮的 有颜色高亮的代码

  • 資深大佬 : across

    引用不可为空。
    且一般编码时你知道确切的创建释放期,就像你说的,栈上函数下调用方便。
    指针就自由度更高点了

  • 主 資深大佬 : James369

    不能编辑了,我贴完整一点:

    //传指针的情况,栈上的 dev 可能会出现段错误
    QNetworkRepley *post1(QNetworkAccessManager& manager) {
    QIODevice dev;
    …
    auto reply = manager->post(request, &dev); //栈上的 dev 可能会出现段错误,如果是 new QIODevice 传指针就没事。
    return reply;
    }

    //传引用的情况,栈上的 data 运行正常:
    QNetworkRepley *post2(QNetworkAccessManager& manager) {
    QByteArray data;
    …
    auto reply = manager->post(request, data); //一切正常
    return reply;
    }

  • 資深大佬 : laminux29

    初学 Cpp,建议多写 Test,多在 Debug 下跑跑,多看看变量值。

    class TestClass
    {
    public:
    int intValue;
    std::string stringValue;
    };

    int main()
    {
    TestClass x1;
    TestClass * x2 = new TestClass();
    断点,展开 x1 与 x2,对比一下。
    }

  • 資深大佬 : wutiantong

    一般不存在你说的这种堆 /栈区别,
    我查了一下,QIODevice 是个抽象基类,是不能直接构建的。
    那么无论是 QIODevice dev; 还是 new QIODevice 都应该要报错的才对。
    要不你再检查一下?

  • 資深大佬 : mxT52CRuqR6o5

    传引用可以看做传指针的语法糖

  • 資深大佬 : XiaoxiaoPu

    跟参数在栈还是堆没关系,纯粹是这两个函数对参数的不同要求。

    *data)
    Sends an HTTP POST request to the destination specified by request and returns a new QNetworkReply object opened for reading that will contain the reply sent by the server. The contents of the data device will be uploaded to the server.

    data must be open for reading and must remain valid until the finished() signal is emitted for this reply.

    注意这一行。第二个函数没有这个要求。

    doc.qt.io/qt-5/qnetworkaccessmanager.html#post

  • 主 資深大佬 : James369

    @wutiantong 你说得对,是我搞错了,应该是 QHttpMultiPart 类。 调用的方法是:QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart);

  • 主 資深大佬 : James369

    @XiaoxiaoPu 那这个参数可以设计成 传引用吗? 为什么

  • 資深大佬 : wutiantong

    @James369

    看起来,之所以是指针( QHttpMultiPart *或 QIODevice *)的原因在于这些类型都是 QObject 的子类,相对的 QNetworkRequest 和 QByteArray 就不是继承自 QObject

    QT 里的 QObject 这套设计应该是很早期的,非常类似于 Objective-C 里的 NSObject,为了与 C 兼容会选择用指针类型来表达对象。

    脱离开 QObject 的类型就更接近于现代 C++,一般是不鼓励用指针传参的,而应该用引用。

  • 資深大佬 : fffang

    写 OC 的表示不知道什么叫引用

  • 資深大佬 : wutiantong

    @wutiantong

    再提一下,基于我对 Objective-C 的了解,如果 QObject 和 NSObject 是差不多的话,那么它的各种子类,都应该在堆上动态分配内存(这一步会涉及到引用计数的内存管理,很可能 QObject 重载了 new 方法)

    所以,你确实不应该在栈上直接构建一个 QObject 的子类对象。

  • 資深大佬 : wutiantong

    @James369

    所以也正是因为 QObject 的子类都必须要在堆上构建,它们才会被声明成指针类型的格式。

  • 主 資深大佬 : James369

    @wutiantong 我之所以会在栈上构建对象,主要因为懒,懒的考虑对象的释放和管理问题,哈哈

  • 資深大佬 : wutiantong

    @James369 你可以理解为参数声明为指针类型就是在提醒你这个参数必须要在堆上构建

  • 資深大佬 : YUCOAT

    引用和指针的一个区别是,存在空指针,但是不存在空引用。

    比如,你设计一个函数 LoadFail:
    bool LoadFile(const FilePath& path, FailReason* reason = nullptr);
    你不希望别人传空 path 进来,这时你可以使用引用。
    但是,reason 可以为空,这时 reason 可以使用指针。

  • 資深大佬 : heyf2015

    传引用必须带着 const,不带 const 时都传指针。基本是这样的约定

  • 資深大佬 : GeruzoniAnsasu

    一般来说,如果接口更接近 C 风格,尤其是跨语言 /跨文件(如动态库)调用时,使用 C 风格并且传指针的麻烦要少得多。 对于 c++ 代码内部来说,引用带有强类型限定,并且可以通过 RAII 管理生命周期,传引用能比较容易避免编译期(代码写得不好)的问题,如悬垂指针、UAF 、资源泄露等等

    不过上面提到了 QT 的设计特例我想多补充一点,QT 的 QObject 默认构造必须带有一个 parent 指针,用于在析构 QObject 时链式释放所有的子对象,这其实有点类似于 IOC,将本对象的生命周期交给自己的容器对象也就是 parent 来管理。 而要想实现 IOC 所需的对象容器,显然对象不可能临时构造在栈上。这也许是使用指针并且总是从堆上构造对象的另一个角度的原因。

  • 資深大佬 : uranuswch

    前司的 code style 要求:
    传入参数 const reference,传出参数 指针

  • 資深大佬 : Wirbelwind

    指针引用看你习惯

  • 資深大佬 : edimetia3d

    .. 印象中很多书都说过这个问题啊, 主要是 style 的问题, 技术层面没有什么优劣, 引用底层也是指针.

    函数传参中, 如果不用拷贝传值, 那么只能用`const T &`或者 `T *`
    `const T &`用于向用户表明: 我一定不会修改传入的对象.
    `T *`用于向用户表明: 我会(极有可能)修改传入的对象.

    从调用方看也能直观的看出来, `func(obj1,&obj2)`,`obj1`要么是 const 引入传入的,要么是拷贝传入,所以一定不会被修改.
    `&obj2`则很有可能在函数 return 后被修改.

    Google Style 应该也是这样的.

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具