在c++中返回对象的最佳方式

Best way to return an object in c++?

本文关键字:最佳 方式 对象 返回 c++      更新时间:2023-10-16

当谈到c++时,我很笨,返回对象的更好方法是什么?我来自脚本世界,对象总是引用,我试图实现相同的概念…我的基础是什么时候通过引用传递,什么时候在c++中通过指针传递?,其中一位用户说:"一条很好的经验法则是:‘尽可能使用引用,必要时使用指针。’"

// basic layer class
class Layer { private: Channel channel; // NEVER NULL };
// return object by pointer
Channel *Layer::getChannel() {
    return &channel;
};
// return by reference
Channel& Layer::getChannel() {
    return channel;
};

第二个版本的问题是编译器会接受这一行:

Channel channel = layer.getChannel();  // creates a copy BAD
Channel &channel = layer.getChannel();  // reference good

是否有办法强制第二个选项的调用者不创建新通道,或者第一个选项更好,即使它永远不会为NULL?

您需要调整Channel类本身,使其不可复制。如果它是可复制的,用户可以复制它,你做什么都不能阻止它。

如果复制不是一个有意义的操作,那么你可以"禁用"它。只需将复制构造函数(Channel(const Channel&))和赋值操作符(Channel& operator=(const Channel&))定义为私有。那么,任何复制该类的尝试都将导致编译错误。

顺便说一句,正如其他人提到的,c++不是您熟悉的脚本语言。一切都不是一个参考,如果你假装不是,你只会让自己陷入一个痛苦的世界。在c++中,通常在堆栈上分配对象,并按值传递对象,而不是传递引用和指针。

返回引用(或const引用)是getter方法让调用者直接访问成员变量的正常方式,因此我建议使用getChannel()的第二个版本。

如果你想防止调用者不适当地复制Channel,你可以通过将它的复制构造函数设为私有来实现。(如果你想防止所有元素复制,甚至Channel本身,你可以声明构造函数private,然后不实现它。)但是,只有在复制实际上是无意义的情况下才应该这样做,例如,如果类代表某种无法复制的底层资源。不要因为你认为调用者不应该需要就禁止复制;这是来电者的决定。

返回对象本身的副本,如果复制对您的目的来说并不昂贵,并且您不需要能够更改原始对象。这应该是默认值。

Channel Layer::getChannel() {     return channel; };

以引用或指针方式返回,当复制开销较大或您可能想要更改值时。通过引用返回允许你做这样的事情:

layer.getChannel().clear();

让它作用于那个层的通道

返回一个指针类似于返回一个引用,除了它给了你更多的灵活性,因为指针可以不指向任何对象。当我想在另一个类中使用存储"通道"时,我经常使用指针。然后我要写

 class MyClass
 {
     // ...
     void setChannel(Channel *pC) { m_pChannel = pC; }
 private:
     Channel * m_pChannel;  // pointer to a channel that came from layer
 }

既然你返回了对对象的引用,你就给了类的用户直接访问对象的权限,如果你要这样做,为什么要把对象设为私有呢?

即使使用指针返回版本,也不能阻止调用者创建新实例。

Channel* channel = new Channel(*layer.getChannel());

我知道有办法达到这个目标。(例如,将channel的actor设为私有,这样只有它的静态成员函数或友元函数才能创建它。)但是,我认为这不是你问题的重点。

关键是,当你让成员函数返回引用或指针时,你给调用者提供了选择的选项,他可以选择是复制还是引用。此外,您可以通过添加const使其为只读,从而使您的意图更加明确。

对于您的情况,我将使用reference-return-version,因为Channel不能为空。如果不希望他们更改成员变量,则返回const引用。记住,没有确定返回值类型的唯一最佳方法,因为它取决于您想要表达的内容。希望能有所帮助!:)

最重要的是保持你周围代码的可读性。"入乡随俗"很重要。你只写一次,但是每个维护你代码的人都要读它。如果突然之间,你的代码遵循的指导方针与你周围的人不同,这意味着他们需要首先弄清楚你的风格,然后弄清楚你在做什么……

我所见过的一种非常有效的方法是使用指针来表示更改的内容,使用const引用来表示不更改的内容:

class Passenger {
  ...
};
class Car {
public:
  int speed() const { return speed_; }
  void set_speed(int speed) { speed_ = speed; }
  const Passenger& passenger() const { return pass_;}
  Passenger* mutable_passenger() { return &pass_; }
private:
  int speed_;
  Passenger pass_;
};

这个类的客户端可以做:

const Passenger& pass = car.passenger();  // no copy, but don't need to deal with NULL ptrs.

其他建议复制编译错误的答案是好的