【发布时间】:2011-02-25 08:38:54
【问题描述】:
没有(显而易见的)首先构建一个 C 风格的字符串,然后使用它来创建一个 std::string,是否有更快/替代/“更好”的方法来从字符向量初始化字符串?
【问题讨论】:
-
不复制也可以吗?换句话说,它与
std::vector<char> v2(std::move(v))做同样的事情,但将std::string作为新对象。
标签: c++
没有(显而易见的)首先构建一个 C 风格的字符串,然后使用它来创建一个 std::string,是否有更快/替代/“更好”的方法来从字符向量初始化字符串?
【问题讨论】:
std::vector<char> v2(std::move(v)) 做同样的事情,但将std::string 作为新对象。
标签: c++
嗯,最好的方法是使用下面的构造函数:
template<class InputIterator> string (InputIterator begin, InputIterator end);
这会导致类似:
std::vector<char> v;
std::string str(v.begin(), v.end());
【讨论】:
我认为你可以做到
std::string s( MyVector.begin(), MyVector.end() );
其中 MyVector 是您的 std::vector。
【讨论】:
_ITERATOR_DEBUG_LEVEL=1(在这种情况下它似乎工作正常)。
使用 C++11,您可以使用std::string(v.data()),或者,如果您的向量末尾不包含'\0',则使用std::string(v.data(), v.size())。
【讨论】:
string(&v[0], v.size()) 也应该可以工作,但只能在assert(not v.empty()); 之后,因为如果向量为空,v[0] 和 v.front()会调用未定义的行为。除了不必使用地址运算符的语法简单性之外,这是 C++11 的 data() 函数的真正好处,它甚至适用于空向量。
std::string(v.data()) 可能会导致更长的字符串。所以不要使用这种方式。
std::string(v.data(), v.size()) 有什么问题,答案中明确提到了这个确切原因?
std::string s(v.begin(), v.end());
其中 v 几乎是任何可迭代的东西。 (特别是 begin() 和 end() 必须返回 InputIterators。)
【讨论】:
我喜欢 Stefan 的回答(2013 年 9 月 11 日),但想让它更强大一点:
如果向量以空终止符结尾,则不应使用 (v.begin(), v.end()):应使用 v.data()(或 &v[0] 用于 C+ 之前的那些) +17)。
如果 v 没有空终止符,则应使用 (v.begin(), v.end())。
如果你使用 begin() 和 end() 并且向量确实有一个终止零,你会得到一个字符串 "abc\0" 例如,它的长度为 4,但实际上应该只有 " abc”。
【讨论】:
(v.begin(), v.end()) 和(v.data()) 之间是否存在性能差异?后者会是O(n)吗?
为了完整起见,另一种方式是std::string(&v[0])(尽管您需要确保您的字符串以空值结尾,并且通常首选std::string(v.data())。
不同之处在于您可以使用前一种技术将向量传递给想要修改缓冲区的函数,而 .data() 则无法做到这一点。
【讨论】:
data()修改缓冲区?在我看来,如果你在非常量向量上调用 data(),它会返回一个 T *(如果你的向量是 const,'v[0]` 无论如何都会返回一个T const &)。跨度>
v 是一个字符串,那将是正确的,但是目标类型是一个字符串并且v 是一个向量。 (但很高兴看到 C++17 将赋予字符串与向量奇偶校验。)
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());
【讨论】: