-1

考虑这个类。

#pragma once

#include <memory>
#include <string>

class A;
class B;

class Test
{
public:
    Test();
    ~Test();

private:
    std::unique_ptr<A> m_a;
    std::unique_ptr<B> m_b;
    std::unique_ptr<std::string> m_string1; // 1
    std::string m_string2; // 2
};

我总是尝试在头文件中转发声明类。但是,我不会对标准头文件这样做,前向声明模板类的 typedef 是很痛苦的。无论如何,如果我有可用的标题 - 我应该更喜欢第一种方式还是第二种方式 -m_string1还是m_string2?我觉得如果我混合使用指针和值类型,那么它看起来会不一致。将所有内容都设为指针是个好主意吗?

4

3 回答 3

1

如果您要这样做,请改用pImpl

class TestImpl;
class Test
{
public:
  Test();
  ~Test();

private:
  std::unique_ptr<TestImpl> m_;
};

在你的 .cpp 文件中,创建一个TestImpl包含所有数据的文件。

这将更好地隐藏您的实现细节,并减少间接性,因为所有数据Test现在都是连贯的(聚集),如果仍然删除了一个间接步骤。

于 2013-04-12T19:52:05.363 回答
1

std::string已经拥有一个动态结构(所以它本身就是一个指针)

毕竟,如果你认为一个字符串是“不透明类型”,那么不透明,你甚至不想包含它的标题,unique_ptr 也应该如此......但你迟早必须停止,否则你最终会得到一类普通指针,重新定义了 big-5(ctor、dtor、copy、assign、move、transfer)。但这每次都在重新实现智能指针。

还要考虑将一个类分解成太小的动态“细节”会在内存中散布对象,从而不允许(或更难)任何基于系统缓存的处理器优化。

如果那时你有一些模板,那么pimpl习惯用法就变得毫无用处:你必须将整个类公开为标题。

在我看来,您对这个成语的应用太深入了。

于 2013-04-12T18:50:27.317 回答
0

您希望它分配在堆上还是可能在堆栈上?有理由使用每种方法(例如对象生命周期),根据情况使用适当的选择。我觉得如果你不需要做指针管理是没有意义的;即使您使用智能指针。

此外,std::string内部类通常是指向堆分配字符串的指针。因此,在这种情况下,您将为单个指针进行堆分配。堆分配比堆栈分配更昂贵,并且许多非常小的分配往往会迅速分割您的堆空间,从而使分配器更难(也就是更慢)找到合理大小的连续可用空间块。

IMO,一般来说一致性是好的,但为了一致性而一致性是僵化和不切实际的。

于 2013-04-12T18:50:52.537 回答