将std::string解释为char_type的std::vector

Interpret a std::string as a std::vector of char_type?

本文关键字:std type vector string 解释 char      更新时间:2023-10-16

我有一个template<typename T>函数,它取const vector<T>&。在上述函数中,我有向量cbegin(), cend(), size()operator[]。据我所知,stringvector都使用连续空间,所以我想知道我是否可以以一种优雅的方式为这两种数据类型重用该函数。

std::string可以被重新解释为(适当的)char_type的std::vector吗?如果是这样,限制是什么?

如果你只为const T&类型制作模板,并使用begin(), end()等向量和字符串共享的函数,那么你的代码将适用于这两种类型

按照STL的方式使用迭代器。接受开始迭代器,结束迭代器。它将适用于所有可能的容器,包括非容器,如流。

不能保证stringvector的布局相同。理论上它们是可以的,但它们可能不在任何常见的实现中。因此,这样做是不安全的。

让我解释一下:如果我是一个标准库的实现者,并决定像这样实现std::string ....

template ...
class basic_string {
public:
    ...
private:
    CharT* mData;
    size_t mSize;
};

并决定像这样实现std::vector

template ...
class vector {
public:
    ...
private:
    T* mEnd;
    T* mBegin;
};

当您使用reinterpret_cast<string*>(&myVector)时,您最终将指向数据结束的指针解释为指向数据开始的指针,并将指向数据开始的指针解释为数据大小。如果成员之间的填充是不同的,或者有额外的成员,它可能会变得更奇怪,更破碎。

所以,是的,为了使这可能工作,他们都需要存储连续的数据,但他们也需要相当多的其他实现之间是相同的工作

std::experimental::array_view<const char> n4512表示一个连续的字符缓冲区。

写你自己的并不难,它解决了这个问题,而且(以我的经验)解决了更多的问题。

string和vector都兼容数组视图。

这允许您将实现移动到.cpp文件中(而不是暴露它),为您提供与使用std::vector<T> const&(可能是相同的实现)相同的性能,避免重复代码,并使用轻量级连续缓冲区类型擦除(其中充满了美味的关键字)。

如果关键是要访问存储特定char类型实例的内存连续区域,那么可以将函数定义为

void myfunc(const CType *p, int size) {
     ...
}

表示您认为它们在内存中必须相邻

例如,要传递vector的内容,代码只需

myfunc(&myvect[0], myvect.size());

和字符串

myfunc(mystr.data(), mystr.size());

myfunc(buffer, n);

不能直接将std::vector类型转换为std::string类型,反之亦然。但是使用STL容器提供的迭代器确实允许您以相同的方式迭代vector和string。如果你的函数需要随机访问有问题的容器,那么这两种方法都可以。

std::vector<char> str1 {'a', 'b', 'c'};
std::string str2 = "abc";
template<typename Iterator>
void iterator_function(Iterator begin, Iterator end)
{
  for(Iterator it = begin; it != end; ++it)
  {
    std::cout << *it << std::endl;
  }
}
iterator_function(str1.begin(), str1.end());
iterator_function(str2.begin(), str2.end());

最后两个函数调用将输出相同的内容。

现在,如果你想写一个通用版本,只解析存储在字符串或向量中的字符,你可以写一些迭代内部数组的东西。

void array_function(const char * array, unsigned length)
{
  for(unsigned i = 0; i < length; ++i)
  {
    std::cout << array[i] << std::endl;
  }
}

这两个函数在下面的场景中会做同样的事情。

std::vector<char> str1 {'a', 'b', 'c'};
std::string str2 = "abc";
iterator_function(str1.begin(), str1.end());
iterator_function(str2.begin(), str2.end());
array_function(str1.data(), str1.size());
array_function(str2.data(), str2.size());

解决问题总是有多种方法。根据您拥有的可用解决方案,任何数量的解决方案都可能有效。两者都尝试一下,看看哪个更适合您的应用程序。如果你不知道迭代器的类型,那么char类型数组迭代是有用的。如果你知道你总是有要传递的模板类型,那么模板迭代器方法可能更有用。

你的问题目前提出的方式有点令人困惑。如果你想问"如果向量恰好包含适当类型的char值,将std::vector类型转换为std::string类型是否安全?",答案是:不可能,甚至不要想它!如果你问:"我可以访问char类型的非空序列的连续内存,如果它们的类型是std::vectorstd::string ?"然后答案是,是的,你可以(与data()成员函数)。

相关文章: