0

全部,

我最近在 DAL 设计上发布了这个问题。由此看来,将对对象的引用传递给函数,然后函数填充该对象,这对于 C++ 数据访问层来说是一个很好的接口,例如

  bool DAL::loadCar(int id, Car& car) {} 

我现在想知道是否使用对 boost::shared_ptr 的引用会更好,例如

  bool DAL::loadCar(int id, boost::shared_ptr<Car> &car)

有什么想法吗?一个比另一个有优势吗?

将 const 正确性应用于两个调用会有什么影响?

提前致谢。

4

4 回答 4

4

正如sbi所说,“这取决于函数的作用。”

但是,我认为上面最重要的方面不是是否允许NULL,而是函数是否存储了指向对象的指针以供以后使用。如果函数只是填写一些数据,那么我会使用参考,原因如下:

  • 该函数仍然可以被不使用 shared_ptr 的客户端使用,用于堆栈对象等。
  • 使用带有 shared_ptr 的函数仍然很简单 - shared_ptr 具有返回引用的取消引用运算符
  • 传递 NULL 是不可能的
  • 少打字
  • 我不喜欢在不需要的时候使用“东西”

如果函数需要存储指针以供以后使用,或者您预计函数可能会以需要存储指针的方式发生变化,则使用 shared_ptr。

于 2009-10-09T10:17:00.900 回答
3

这取决于函数的作用。

一般来说,一个带有指针的函数表明调用者可能会调用这个函数,即使他们没有要传递给它的对象——他们总是可以传递NULL. 如果这符合函数的规范,则使用(智能)指针。通过引用传递引用计数智能指针而不是复制它们是一种优化(而不是过早的优化,我应该补充),因为它避免了不必要的增加和减少引用计数,这在 MT 环境中可能会显着影响性能。

将非常量引用作为参数的函数期望传递一个它可能会更改的有效对象。调用者不能(合法地)调用该函数,除非他们有一个有效的对象,并且除非他们愿意让函数改变对象的状态,否则他们不会调用它。如果这更符合函数的规范,请使用参考。

于 2009-10-09T09:45:14.847 回答
1

如果您必须接收一个有效的对象(即您不希望调用者传递 NULL),那么无论如何不要使用 boost::shared_ptr。您的第二个示例传递了对“智能指针”的引用....忽略细节,它是“指向 Car 的指针”。因为它是引用,所以 shared_ptr 对象不能为 NULL.... 但这并不意味着它不能有 NULL 值(即指向“null”对象)。

我不明白为什么您会认为对智能指针的引用会“更好”——调用者函数是否已经使用智能指针?

至于“const”的含义......你的意思是什么

bool DAL::loadCar(int id, const Car& car) {}

? 如果是,那将适得其反,您向编译器传达“汽车”不会改变的事实(但可能您希望它改变!)。

或者你的意思是让函数“const”,比如

class DAL{
   bool loadCar(int id, Car& car) const;
}

?

在后一种情况下,您向编译器/API 用户传达方法“loadCar”不会修改 DAL 对象。如果这是真的,那么这样做是个好主意 - 不仅因为它启用了一些编译器优化,而且在“合同”(函数签名)中指定函数不对 DAL 进行任何修改通常是一件好事,特别是如果你在你的代码中做了这个隐含的假设(这样你可以确保这保持真实,并且将来没有人会以改变“DAL”对象的方式修改“loadCar”函数)

于 2009-10-09T10:15:19.563 回答
0

在第一种情况下,您只需传递一个 Car 并用信息“填充”它。例如,您可以创建一个“默认”汽车,然后填充它。我从中看到了一个不便:拥有两类 Car 并不是很 OO:一类是糟糕的、默认的、无用的、“空”的 Car,另一类是从函数中真正填充的 Car。对我来说,汽车就是汽车,所以它应该是在您的功能之前和之后有效的汽车(例如,我可以从位置 A 开车到 B;我可以加速、制动、启动、停止的汽车)。

我通常使用传统指针,而不是 boost(顺便说一句,没有问题),所以我真的无法评论后一种选择。

于 2009-10-09T09:34:26.767 回答