假设我有一个类Obj,并且它们的实例是在运行时创建的,我可以不new这样存储它们吗?
Obj my_obj;
std::vector<Obj> my_vec;
my_vec.push_back(my_obj);
Run Code Online (Sandbox Code Playgroud)
还是我必须使用新的?
std::vector<Obj*> my_vec;
my_vec.push_back(new Obj);
Run Code Online (Sandbox Code Playgroud)
如果我的类中有指针怎么办Obj?另外,如果使用第二个选项,我需要清理所有东西吗?
这个问题与堆分配对象与堆栈对象有关。Stackoverflow 中已经有一些很好的资源:
(你可能想看看上面所有的内容,每个都有自己的角度)。
但是,您的问题具体是关于保存对象或指向对象的指针的容器。为此,还有一些其他资源:
让我简短地总结一下:
通常使用值而不是指针应该是您的首选。它们更容易维护并且更不易出现错误。在 C++11 之前,性能考虑可能是考虑使用指针容器的一个原因,但由于移动语义出现在 C++11 中,如果正确设计代码,使用值容器的成本应该不会很高。
使用指针的另一个原因可能是多态性。您希望容器保存和管理共享相同基类的不同类型。尽管指针容器似乎应该是这种情况下的解决方案(在 C++ 中的多态性的许多示例中都使用了指针容器),但这仍然不应该是您的首选。原始指针的第一个替代方案应该是 Holding,unique_ptr它是 C++11 中 C++ 标准库中引入的智能指针类型。
另一种选择是使用一个类对您想要管理的数据进行建模,该类将隐藏和管理您的多态性,而不会将其暴露给容器或用户。让我们举个例子:假设您要管理一个 Command 对象的容器,其中 Command 是许多不同实际命令的基类。Command*不要使用or的容器unique_ptr<Command>,而是将 Command 重命名为 CommandBase,然后unique_ptr<CommandBase>在类中保留(包装、隐藏)Command并保存类型为 的容器对象Command。
另一种选择是完全避免继承。因此,对于不同的可调用对象(我们的命令示例),您可以只使用std::function.
您还可以使用std::variant来管理不同的类型(例如using Shape = std::variant<Circle, Triangle>;)。
隐藏您正在使用多态性的事实,或者完全避免多态性,在您的 API 中可能会变得非常有用,并且能够保留正确的值语义。
有关值语义及其优点的更多信息,请参阅 Klaus Iglberger 的 CppCon 2022 演讲:回归基础:Cpp 值语义和 Dave Abrahams 的 C++Now 2022 演讲:价值语义和泛型编程的未来,第1 部分和第 2 部分2 . Sean Parent 关于该主题的原始演讲:价值语义和基于概念的多态性,来自 C++Now 2012。
您还可以在以下链接中阅读有关值语义的信息:
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |