我想知道如何为需要大量内存的成员变量使用getters和setters方法。通常我会像下面这样:
class A
{
private:
BigObject object;
public:
BigObject getObject() const
{
return object;
}
void setObject(const BigObject& object)
{
this->object = object;
}
};
但是我相信这个getter和setter方法会复制我不想要的BigObject。有更好的方法吗?
我考虑过这样做,但是我在互联网上读到,这不是一个好主意,因为如果使用不当,可能会导致细分错误:
BigObject& getObject()
{
return object
}
答案 0 :(得分:6)
(如果您在这种情况下不关心封装,则意味着A::object
成员可以不受任何限制地被任何人修改,然后查看SergeyA's answer)。
通过const引用返回以避免复制并仍然保持封装(这意味着调用者不能错误地修改成员):
const BigObject& getObject() const
{
return object;
}
如果呼叫者确实想要复制,他们可以自己轻松进行复制。
如果要防止在临时使用getter时悬挂引用(提到的段错误),则只能在实际在临时上调用getter时返回副本:
BigObject getObject() const &&
{
return object;
}
const BigObject& getObject() const &
{
return object;
}
在临时调用getObject()
时,它将返回一个副本。另外,您可以通过删除特定的重载完全阻止临时调用getter:
BigObject getObject() const && = delete;
const BigObject& getObject() const &
{
return object;
}
请记住,这不是保证的安全网。它可以防止某些错误,但不是全部。函数的调用者仍应了解对象的生存期。
您还可以改善二传手。现在,无论调用者如何传递参数,它都将始终复制对象。您应该改为按值取值并将其移入成员:
void setObject(BigObject object)
{
this->object = std::move(object);
}
这需要BigObject
可以移动。如果不是这样,那将比以前更糟。
答案 1 :(得分:4)
最佳解决方案:准确地为您的类编写代码:
struct A
{
BigObject object;
};
说明-避免琐碎的设置者和获取者。如果您发现自己将这些内容放到班级中,请直接公开该成员并完成操作。
永远不要听那些会说“但是如果将来我们添加非平凡逻辑”的人呢?我看到的不仅仅是健康的琐碎吸气剂,而且已经使用了数十年,而且从未被非琐碎的东西所取代。
答案 2 :(得分:2)
常见的做法是:
class A
{
public:
// this method is const
const& BigObject getObject() const
{
return object;
}
// this method is not const
void setObject(const BigObject& object)
{
object = object;
}
private:
BigObject object;
};
如果您需要获取只读对象-很好。否则,请考虑更改体系结构。
一种替代方法是存储std::shared_ptr
并返回std::shared_ptr
或std::weak_ptr
。
答案 3 :(得分:1)
您可以返回对该成员的引用,而不是返回该成员的副本。这样就无需复制成员。
我考虑过这样做,但是我在互联网上读到它不是一个好主意,因为如果使用不当,可能会导致细分错误
解决方案是不要不好用它。
返回对成员的引用是很常见的模式,通常不建议这样做。尽管对于快速复制的类型,当不需要引用成员本身时,通常返回副本更好。
有一种避免复制和破坏封装的解决方案:使用共享指针,并从getter返回该共享指针的副本。但是,这种方法具有运行时成本,并且需要动态分配,因此并非适用于所有用例。
在使用setter的情况下,您可以使用移动分配,这比某些类型的复制分配更有效。