1
James369 OP 另外,顺便问下怎么贴漂亮的 有颜色高亮的代码
|
2
across 2021-01-26 10:05:38 +08:00 via iPhone
引用不可为空。
且一般编码时你知道确切的创建释放期,就像你说的,栈上函数下调用方便。 指针就自由度更高点了 |
3
James369 OP 不能编辑了,我贴完整一点:
//传指针的情况,栈上的 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; } |
4
laminux29 2021-01-26 11:07:59 +08:00
初学 Cpp,建议多写 Test,多在 Debug 下跑跑,多看看变量值。
class TestClass { public: int intValue; std::string stringValue; }; int main() { TestClass x1; TestClass * x2 = new TestClass(); 断点,展开 x1 与 x2,对比一下。 } |
5
wutiantong 2021-01-26 11:29:22 +08:00
一般不存在你说的这种堆 /栈区别,
我查了一下,QIODevice 是个抽象基类,是不能直接构建的。 那么无论是 QIODevice dev; 还是 new QIODevice 都应该要报错的才对。 要不你再检查一下? |
6
mxT52CRuqR6o5 2021-01-26 11:30:41 +08:00
传引用可以看做传指针的语法糖
|
7
XiaoxiaoPu 2021-01-26 11:34:30 +08:00
跟参数在栈还是堆没关系,纯粹是这两个函数对参数的不同要求。
*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 |
8
James369 OP @wutiantong 你说得对,是我搞错了,应该是 QHttpMultiPart 类。 调用的方法是:QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart);
|
9
James369 OP @XiaoxiaoPu 那这个参数可以设计成 传引用吗? 为什么
|
10
wutiantong 2021-01-26 11:50:52 +08:00
@James369
看起来,之所以是指针( QHttpMultiPart *或 QIODevice *)的原因在于这些类型都是 QObject 的子类,相对的 QNetworkRequest 和 QByteArray 就不是继承自 QObject QT 里的 QObject 这套设计应该是很早期的,非常类似于 Objective-C 里的 NSObject,为了与 C 兼容会选择用指针类型来表达对象。 脱离开 QObject 的类型就更接近于现代 C++,一般是不鼓励用指针传参的,而应该用引用。 |
11
fffang 2021-01-26 11:54:31 +08:00
写 OC 的表示不知道什么叫引用
|
12
wutiantong 2021-01-26 11:55:25 +08:00
@wutiantong
再提一下,基于我对 Objective-C 的了解,如果 QObject 和 NSObject 是差不多的话,那么它的各种子类,都应该在堆上动态分配内存(这一步会涉及到引用计数的内存管理,很可能 QObject 重载了 new 方法) 所以,你确实不应该在栈上直接构建一个 QObject 的子类对象。 |
13
wutiantong 2021-01-26 11:57:27 +08:00
|
14
James369 OP @wutiantong 我之所以会在栈上构建对象,主要因为懒,懒的考虑对象的释放和管理问题,哈哈
|
15
wutiantong 2021-01-26 12:05:28 +08:00 via Android 1
@James369 你可以理解为参数声明为指针类型就是在提醒你这个参数必须要在堆上构建
|
16
YUCOAT 2021-01-26 12:08:28 +08:00
引用和指针的一个区别是,存在空指针,但是不存在空引用。
比如,你设计一个函数 LoadFail: bool LoadFile(const FilePath& path, FailReason* reason = nullptr); 你不希望别人传空 path 进来,这时你可以使用引用。 但是,reason 可以为空,这时 reason 可以使用指针。 |
17
heyf2015 2021-01-26 13:09:37 +08:00
传引用必须带着 const,不带 const 时都传指针。基本是这样的约定
|
18
GeruzoniAnsasu 2021-01-26 13:54:05 +08:00
一般来说,如果接口更接近 C 风格,尤其是跨语言 /跨文件(如动态库)调用时,使用 C 风格并且传指针的麻烦要少得多。 对于 c++ 代码内部来说,引用带有强类型限定,并且可以通过 RAII 管理生命周期,传引用能比较容易避免编译期(代码写得不好)的问题,如悬垂指针、UAF 、资源泄露等等
不过上面提到了 QT 的设计特例我想多补充一点,QT 的 QObject 默认构造必须带有一个 parent 指针,用于在析构 QObject 时链式释放所有的子对象,这其实有点类似于 IOC,将本对象的生命周期交给自己的容器对象也就是 parent 来管理。 而要想实现 IOC 所需的对象容器,显然对象不可能临时构造在栈上。这也许是使用指针并且总是从堆上构造对象的另一个角度的原因。 |
19
uranuswch 2021-01-26 13:57:13 +08:00
前司的 code style 要求:
传入参数 const reference,传出参数 指针 |
20
Wirbelwind 2021-01-26 15:22:16 +08:00
指针引用看你习惯
|
21
edimetia3d 2021-01-26 23:22:11 +08:00
.. 印象中很多书都说过这个问题啊, 主要是 style 的问题, 技术层面没有什么优劣, 引用底层也是指针.
函数传参中, 如果不用拷贝传值, 那么只能用`const T &`或者 `T *` `const T &`用于向用户表明: 我一定不会修改传入的对象. `T *`用于向用户表明: 我会(极有可能)修改传入的对象. 从调用方看也能直观的看出来, `func(obj1,&obj2)`,`obj1`要么是 const 引入传入的,要么是拷贝传入,所以一定不会被修改. `&obj2`则很有可能在函数 return 后被修改. Google Style 应该也是这样的. |
22
intlinfo 2021-02-08 02:23:51 +08:00
指针自由度高,引用并非不可为空,在设计上引用也可以为 nil
两者都是指向同一内存地址,只是 指针是 -> 引用是 . 在多线程的情况下,引用直接引用原有地址。 基础指针引用原有地址,c++11 智能指针传参时会涉及到复制。 具体多谢 test 自行测试观察为好。要讲理论我不行嘿嘿,但是实际上写代码还是会注意这些问题的,经验积累的。 拒绝脑残面试官让你讲理论。 :) |