我有一个template<typename T>
函数需要const vector<T>&
。在所述函数中,我有向量cbegin()
,cend()
,size()
和operator[]
。
据我所知,string
和vector
都使用了连续的空间,所以我想知道我是否可以优雅地重用这两种数据类型的函数。
可以将std::string
重新解释为(适当的)char_type的std::vector
吗?如果是这样,那么限制是什么?
答案 0 :(得分:13)
如果您只为类型const T&
创建模板,并使用begin()
,end()
等,包含vector和string共享的函数,那么您的代码将适用于这两种类型。< / p>
答案 1 :(得分:7)
以STL方式使用迭代器。接受迭代器开始,迭代器结束。它适用于所有可能的容器,包括非容器,如流。
答案 2 :(得分:6)
无法保证string
和vector
的布局相同。理论上它们可能是,但它们可能不是任何常见的实现。因此,您无法安全地执行此操作。有关更好的解决方案,请参阅Zan的答案。
让我解释一下:如果我是一个标准的库实现者,并决定像这样实现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)
时,你最终会将指向数据末尾的指针解释为指向数据开头的指针,并将指向数据开头的指针解释为数据大小。如果成员之间的填充不同,或者有额外的成员,那么它甚至可能变得更奇怪,也更加破碎。
所以是的,为了使它们可以工作,它们都需要存储连续的数据,但它们在实现它们之间还需要相同的其他工作。
答案 3 :(得分:5)
std::experimental::array_view<const char>
n4512表示字符的连续缓冲区。
写your own is not hard,它解决了这个问题和(根据我的经验)更多。
字符串和向量都与数组视图兼容。
这使您可以将实现移动到.cpp
文件中(并且不公开它),提供与使用std::vector<T> const&
执行相同的性能,并且可能具有相同的实现,避免重复代码和使用轻量级连续缓冲类型擦除(其中充满了美味的关键词)。
答案 4 :(得分:2)
如果关键点是你想要访问存储器中存储特定字符类型实例的连续区域,那么你可以将你的函数定义为
void myfunc(const CType *p, int size) {
...
}
清楚地表明你认为它们必须在内存中相邻。
然后例如传递向量的内容,代码就是
myfunc(&myvect[0], myvect.size());
和字符串
myfunc(mystr.data(), mystr.size());
或
myfunc(buffer, n);
表示数组。
答案 5 :(得分:1)
您无法直接将std :: vector类型转换为std :: string,反之亦然。但是使用STL容器提供的迭代器确实允许您以相同的方式迭代向量和字符串。如果你的函数需要随机访问有问题的容器,那么任何一个都可以工作。
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类型数组迭代很有用。如果您知道将始终传递模板类型,则模板迭代器方法可能更有用。
答案 6 :(得分:0)
目前提出问题的方式有点令人困惑。如果您要问“将std::vector
类型转换为std::string
类型是否安全,反之亦然,如果向量恰好包含相应类型的char值?”,答案是:no方式,甚至不要考虑它!如果你问:“如果它们属于std::vector
或std::string
类型,我可以访问非空的char类型序列的连续内存吗?”然后答案是,是的,你可以(使用data()
成员函数)。