c++ - std::size_t 与 size_type 作为参数和函数返回类型

标签 c++ encapsulation c++98 size-t size-type

假设我有这段代码。哪种方法更好?

// Method 1
std::size_t size()
{
  // m_myVector is of type std::vector<MyClass*> in all examples
  return m_myVector.size();
}

// Method 2
std::vector<MyClass*>::size_type size()
{
  // m_myVector is of type std::vector<MyClass*> in all examples
  return m_myVector.size();
}

第一种方法适用于 99% 的情况,但当然也有可能 vector 的大小不是 std::size_t 类型。 。也就是说,我们可以依靠软件分析工具来告诉我们 vector 大小的返回类型已经改变了。

第二种方式向调用者公开 vector 的实现细节。这会破坏封装吗?我不知道,你告诉我!

这是另一个更复杂的示例。哪种方法更好?

void doFoo(const SomeClass& someObject)
{
  // These could be ints or size_types... Feel free to use your imagination
  std::size_t firstCount = someObject.getFirstCount();
  for (std::size_t i = 0U; i < firstCount; ++i)
  {
    foo(firstCount);
  }
}

void doFoo2(const SomeClass& someObject)
{
  // I thought I'd provide another example to help your imagination :)
  std::vector<MyClass*>::size_type secondCount = someObject.getSecondCount();
  for (std::vector<MyClass*>::size_type i = 0U; i < secondCount; ++i)
  {
    foo(secondCount);
  }
}

void doFoo3(const SomeClass& someObject)
{
  // The correct styling would be: NotMyClass*
  // But I really wanted to emphasize this was different from above, so I ALL CAPPED IT
  std::vector<NOTMYCLASS*>::size_type thirdCount = someObject.getThirdCount();
  for (std::vector<NOTMYCLASS*>::size_type i = 0U; i < thirdCount; ++i)
  {
    foo(thirdCount);
  }
}

// Method 1
void foo(std::size_t index)
{
  // m_myVector is of type std::vector<MyClass*> in all examples
  m_myVector.at(index)->doLotsOfStuff();
}

// Method 2
void foo(std::vector<MyClass*>::size_type index)
{
  // m_myVector is of type std::vector<MyClass*> in all examples
  m_myVector.at(index)->doLotsOfStuff();
}

好吧,这是一个很长的例子,所以我会解释一下发生了什么。 doFoo() , doFoo2() ,和doFoo3()欢迎调用foo()它接受 std::size_t在第一个实现中或 std::vector<MyClass*>::size_type在第二次实现中。

doFoo()正在传递 std::size_tfoo() ,所以先执行foo()这里更有意义,但是我们索引 std::vector<MyClass*>期待 std::vector<MyClass*>::size_type 。不是特别好如果 size_type未定义为std::size_t .

doFoo2()正在传递 std::vector<MyClass*>::size_typefoo() ,所以第二次执行foo()在这里工作得很好。除了向调用者公开私有(private) vector 的实现细节之外,没有任何提示。最后我想我们需要 include a separate header for MyClass .

doFoo3()正在传递 std::vector<NOTMYCLASS*>::size_typefoo() ...并且 foo() 都没有实现期望如此,因为 foo() 的唯一 vector 关心的是保存 MyClass* 类型元素的 vector 。现在,作为一个学术问题,是std::vector<NOTMYCLASS*>::size_type始终与 std::vector<MyClass*>::size_type 相同?我实际上不知道这个问题的答案,但我一直听到'yes' and 'no' 。最后,再次存在封装问题(如果这是一个问题)。

无论如何,谢谢你对我的包容。想法?

最佳答案

but of course there's the off-chance that the size of the vector isn't of type std::size_t

这种情况实际上并不存在,因为 std::vector<MyClass*>::size_type (间接保证并要求)类型为 std::size_t 。使用std::size_t在这种情况下没问题,并且不会泄漏不必要的实现细节。


对于标准容器,Container::size_type直接根据正在使用的分配器来定义。因此,使用 size_type通常仅当分配器类型或容器类型本身被模板化时才需要。在分配器情况下,您可以使用分配器特征而不是容器成员类型,这允许您隐藏容器类型。如果容器类型本身是模板化的,那么隐藏它就没有意义,因为只有知道容器的人才能首先实例化模板。

此外,您可以通过创建类型别名成员来隐藏 - 或者更确切地说混淆(以积极的封装方式)函数声明,就像 std::vector 一样。有一个基于其分配器的类型别名成员。

示例:

template<class Alloc>
class Foo
{
    // could be hidden with PIMPL if desired
    std::vector<MyClass*, Alloc> m_myVector;

public:
    // Since C++11
    using size_type = typename std::allocator_traits<Alloc>::size_type;
    // Prior to C++11
    typedef typename Alloc::size_type size_type;
    
    size_type size();
};

关于c++ - std::size_t 与 size_type 作为参数和函数返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65586859/

相关文章:

c++ - 头文件/cpp 文件中定义的函数表现不同

c++ - "Hello World"运行失败。 Windows Vista 上 MinGW 和 Cygwin 的 Eclipse (Galileo) CDT 插件问题

c++ - 为什么 boost::hana 的集合不能默认构造?

c++ - 什么时候我应该更喜欢非成员非 friend 函数而不是成员函数?

c++ - 使用 C++98 标准填充二维静态 vector

c++ - 平方根递归

perl - Perl 中的数据封装?

python - 当它永远不会被实例化时,在 python 中创建一个类是否有意义?

c++ - 来自字符串的 GUID

c++ - boost::this_thread::sleep_用于使整个程序休眠