所以我有一个std::string
并且有一个函数需要char*
并写入它。由于std::string::c_str()
和std::string::data()
返回const char*
,我无法使用它们。所以我分配了一个临时缓冲区,用它调用一个函数并将其复制到std::string
。
现在我计划处理大量信息,复制此缓冲区会产生明显的影响,我想避免它。
有些人建议使用&str.front()
或&str[0]
,但会调用未定义的行为吗?
答案 0 :(得分:17)
不可能。字符串可以在写入时进行复制,因此需要处理所有读写操作。
在[string.require]中:
basic_string
对象中类似char的对象应连续存储。也就是说,任何basic_string
对象s
,&*(s.begin() + n) == &*s.begin() + n
的所有值都应保留n
0 <= n < s.size()
。
因此&str.front()
和&str[0]
应该有效。
str.data()
,&str.front()
和&str[0]
工作。
Here它说:
charT* data() noexcept;
返回:指针
p
,p + i == &operator[](i)
中每个i
的{{1}}。复杂性:恒定时间。
要求:程序不得更改存储的值
[0, size()]
。
非const at p + size()
正常运作。
recent draft对.data()
有以下措辞:
.front()
const charT& front() const;
需要:
charT& front();
。效果:相当于
!empty()
。
以下operator[](0)
:
operator[]
const_reference operator[](size_type pos) const;
需要:
reference operator[](size_type pos);
。返回:
pos <= size()
。否则,返回对值为*(begin() + pos) if pos < size()
的{{1}}类型的对象的引用,其中修改对象会导致未定义的行为。投掷:没什么。
复杂性:恒定时间。
所以它使用迭代器算法。所以我们需要检查有关迭代器的信息。 Here它说:
3 basic_string是一个连续的容器([container.requirements.general])。
所以我们需要去here:
连续容器是一个容器,它支持随机访问迭代器([random.access.iterators]),其成员类型
charT
和charT()
是连续的迭代器([iterator.requirements.general])
然后here:
迭代器进一步满足以下要求:对于整数值n和可解除引用的迭代器值
iterator
和const_iterator
,a
等同于(a + n)
,称为连续迭代器。
显然,连续迭代器是C ++ 17的一项功能,已在these papers中添加。
该要求可以改写为:
*(a + n)
因此,在第二部分中我们取消引用迭代器,然后获取它指向的值的地址,然后对其执行指针算法,取消引用它,它与递增迭代器然后解除引用它相同。这意味着连续的迭代器指向内存,其中每个值都紧接着存储,因此是连续的。由于*(addressof(*a) + n)
的函数需要连续的内存,因此您可以将assert(*(a + n) == *(&*a + n));
或char*
的结果传递给这些函数。
答案 1 :(得分:0)
您可以简单地将&s[0]
用于非空字符串。这为您提供了指向缓冲区开头的指针
当你使用它来放置一串 n 字符时,string
的长度(不仅仅是容量)至少需要 n 事先,因为没有办法在没有破坏数据的情况下进行调整。
即,使用情况可以是这样的:
auto foo( int const n )
-> string
{
if( n <= 0 ) { return ""; }
string result( n, '#' ); // # is an arbitrary fill character.
int const n_stored = some_api_function( &result[0], n );
assert( n_stored <= n );
result.resize( n_stored );
return result;
}
自C ++ 11以来,这种方法已经正式运作。在此之前,在C ++ 98和C ++ 03中,缓冲区未正式保证是连续的。然而,对于实践中这种方法自C ++ 98以来已经起作用,这是第一个标准 - 在C ++ 11中可以采用连续缓冲区要求的原因(它在Lillehammer会议中被添加,我认为是2005年)是没有现有的标准库实现与非连续的字符串缓冲区。
关于
“ C ++ 17添加了非常量
data()
添加到std::string
,但它仍然表示您无法修改缓冲区。
我不知道有任何这样的措辞,因为这会破坏非常规data()
的目的,我怀疑这种说法是正确的。
关于
“现在我计划处理大量信息,复制此缓冲区会产生明显的影响,我想避免它。
如果复制缓冲区有明显的影响,那么您需要避免无意中复制std::string
。
一种方法是将它包装在一个不可复制的类中。
答案 2 :(得分:0)
我不知道你打算用string
做什么,但如果是
你需要的只是一个字符缓冲区,它可以自动释放自己的内存,
然后我通常使用vector<char>
或vector<int>
或任何类型的
您需要的缓冲区。
以v
为向量,保证&v[0]
指向
一个顺序存储器,可以用作缓冲区。