如何从std :: vector <char>构造std :: string?


115

缺少(显而易见的)首先要构建C风格的字符串,然后使用它来创建std :: string,是否有更快/替代/“更好”的方式从chars向量中初始化字符串?


4
可以不复制就完成吗?换句话说,某事物std::vector<char> v2(std::move(v))std::string新事物具有相同的作用,但具有a 的作用。
tobi_s

Answers:


197

好吧,最好的方法是使用以下构造函数:

template<class InputIterator> string (InputIterator begin, InputIterator end);

这将导致类似:

std::vector<char> v;
std::string str(v.begin(), v.end());

41

我想你可以做

std::string s( MyVector.begin(), MyVector.end() );

MyVector是您的std :: vector。


1
VS2013除外,VS2013会在运行时声明无效的迭代器,除非您进行了设置_ITERATOR_DEBUG_LEVEL=1(在这种情况下,它似乎可以正常工作)。
卡梅伦

35

使用C ++ 11,您可以这样做,std::string(v.data())或者如果向量'\0'的末尾不包含,则可以这样做std::string(v.data(), v.size())


即使使用C ++ 98,我相信您也可以执行std :: string(&v [0])。当然,这是向量为空终止的情况。
Jamie

1
@Jamie:顺便说一下,在C ++ 98,string(&v[0], v.size())应该也行,但只有后assert(not v.empty());,因为如果向量为空,v[0]v.front()会调用未定义的行为。除了不必使用address-of运算符的语法简单性之外,这是C ++ 11 data()函数的真正好处,该函数甚至可以在空向量上运行。
亚当·彼得森

非常真实 不幸的是,在可预见的将来,我的项目仍停留在Visual Studio 2008上。关于首先检查向量长度的权利。
杰米

如果vector不包含'\ 0',则std::string(v.data())可能导致更长的字符串。所以不要使用这种方式。
heLomaN

@heLomaN:到底有什么问题std::string(v.data(), v.size()),正是出于这个确切原因在答案中提到了?
Sz。

12
std::string s(v.begin(), v.end());

其中v几乎是可迭代的。(特别是begin()和end()必须返回InputIterators。)


3

只是为了完整性,另一种方法是std::string(&v[0])(尽管您需要确保您的字符串以null结尾,std::string(v.data())并且通常是首选的。

不同之处在于,您可以使用前一种技术将向量传递给要修改缓冲区的函数,而使用.data()则不能。


为什么不能使用data()修改缓冲区?在我看来,如果您调用data()非const向量,它将返回a T *(如果您的向量为const,则“ v [0]`仍将返回” T const &)。
亚当·彼得森

@ AdamH.Peterson似乎是对标准的疏忽。Std :: vector的数据同时具有const和非const函数,而在当前标准中,std :: string仅具有const函数:en.cppreference.com/w/cpp/string/basic_string/data 请注意,C ++ 17添加了一个非const版本,因此可能不是无限期的情况-但是,当前标准状态为“修改通过数据访问的字符数组具有未定义的行为”。
暴动

如果v是字符串,那将是正确的,但是目标类型是字符串并且v是向量。(但很高兴看到C ++ 17将使字符串与向量保持奇偶校验。)
Adam H. Peterson16年

@ AdamH.Peterson当然是对的。这个问题是在不久前回答的,我以为整个问题都是关于字符串的,没有经过检查。
骚乱

2

我喜欢Stefan的回答(13年9月11日),但想使其更强一点:

如果向量以空终止符结尾,则不应使用(v.begin(),v.end()):应使用v.data()(对于C ++ 17之前的版本,则为&v [0]) 。

如果v没有空终止符,则应使用(v.begin(),v.end())。

如果您使用begin()和end()并且向量确实有一个终止的零,则最终将得到一个字符串“ abc \ 0”,该字符串的长度为4,但实际上应该仅为“ abc”。


1
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());

您能添加一些解释以及代码吗?
保罗·弗洛伊德

1
C ++ 11字符串库模板如下所示:默认(1)string(); 复制(2)字符串(const string&str); 子字符串(3)字符串(const string&str,size_t pos,size_t len = npos); 从c字符串(4)字符串(const char * s); 从缓冲区(5)字符串(const char * s,size_t n); 填充(6)字符串(size_t n,char c); 范围(7)模板<class InputIterator>字符串(首先输入InputIterator,最后输入InputIterator);初始化列表(8)字符串(initializer_list <char> il); 移动(9)字符串(string && str)noexcept; 我们正在关注第7个模板。
TechCat

嗨@TechCat!在回答下一个问题之前,请先仔细阅读如何写一个好的答案。祝您逗留愉快!
Diggy。

您能用说明来编辑答案吗?
保罗·弗洛伊德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.