合法覆盖std :: string null终止符?

时间:2012-10-05 06:03:42

标签: c++ c++11 language-lawyer stdstring

在C ++ 11中,我们知道std::string保证是连续的并且以空值终止(或更加迂腐,由charT()终止,在char的情况下是空字符0)。

我需要使用这个C API,通过指针填充字符串。它写入整个字符串+ null终止符。在C ++ 03中,我总是被迫使用vector<char>,因为我不能假设string是连续的或空终止的。但是在C ++ 11中(假设一个正确符合的basic_string类,在某些标准库中仍然是不合适的),我可以。

或者我可以吗?当我这样做时:

std::string str(length);

字符串将分配length+1个字节,最后一个由空终止符填充。非常好。但是,当我将其传递给C API时,它将写入length+1个字符。它将覆盖null终止符。

不可否认,它将使用空字符覆盖null-terminator 。这种情况很有用(事实上,我无法想象无法工作)。

但我并不关心“有效”。我想知道,根据规范,是否可以用空字符覆盖null终止符?

4 个答案:

答案 0 :(得分:25)

不幸的是,这是UB,如果我将措辞解释正确(无论如何,它是不允许的):

§21.4.5 [string.access] p2

  

返回: *(begin() + pos) if pos < size(),否则引用类型为T且价值为charT()的对象; 不得修改参考值

(编辑错误,它说T而非charT。)

.data().c_str()基本上回到operator[]§21.4.7.1 [string.accessors] p1):

  

返回:指针pp + i == &operator[](i)中的每个i [0,size()]

答案 1 :(得分:11)

根据规范,覆盖终止NUL应该是未定义的行为。 因此,正确的做法是在字符串中分配length+1个字符,将字符串缓冲区传递给C API,然后resize()返回length

// "+ 1" to make room for the terminating NUL for the C API
std::string str(length + 1);

// Call the C API passing &str[0] to safely write to the string buffer
...

// Resize back to length
str.resize(length);

(FWIW,我在MSVC10上尝试了“覆盖NUL”方法,它运行正常。)

答案 2 :(得分:9)

LWG 2475通过编辑operator[](size())的规范(以粗体显示插入的文字)使其有效:

  

否则,返回对值为charT的对象的引用   charT(),将对象修改为charT() 以外的任何值   导致未定义的行为。

答案 3 :(得分:5)

我认为n3092不再是现在,但这就是我所拥有的。第21.4.5节允许访问单个元素。它需要pos&lt; = size()。如果pos&lt; size()然后你得到实际的元素,否则(即如果pos == size())那么你得到一个不可修改的引用。

我认为就编程语言而言,即使新值与旧值相同,也可以将一种可以修改该值的访问视为修改。

g ++是否有可以链接的迂腐图书馆?