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

Nic*_*las 37 c++ stdstring language-lawyer c++11

在C++ 11中,我们知道std::string保证是连续的和以null结尾的(或更迂腐,终止于charT(),在char空字符0 的情况下).

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

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

std::string str(length);
Run Code Online (Sandbox Code Playgroud)

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

不可否认,它将用空字符覆盖null终止.赔率是好的,这将工作(事实上,我无法想象它怎么可能不工作).

但我不关心什么"有效".我想知道,根据规范,是否可以用空字符覆盖null终止符?

Xeo*_*Xeo 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):

返回:一个指针p,p + i == &operator[](i)用于每个iin [0,size()].

  • 将'\ 0'写入已经'\ 0'的东西实际上算是修改它吗? (8认同)
  • @MichaelAnderson,是的,绝对.它写入内存. (6认同)
  • @NicolBolas编号`size()`是`operator []`的无效参数,所以没有什么能保证它的返回值指向缓冲区.例如(far-fetched),`operator []`可以包含以下逻辑:`static CharT terminator {}; if(index == size())返回终止符; 否则返回_data [i];`. (3认同)
  • @KonradRudolph好吧,`data`和`c_str`返回const指针,所以无论如何它们都无法修改.从21.4.5 p2开始,它并不真正遵循`*(&str [0] + str.size())`甚至是允许的,因为`[]`只等于`*(begin()+ pos) `for`post <size()`.我认为完全允许一个实现将字符串数据保存在一个`length`数组中,同时还有另一个`static const charT`成员用于null(当然这意味着它必须维护一个额外的缓冲区来返回`data`和`c_str`,但为什么不呢?). (2认同)
  • @KonradRudolph:必须这样做.缓冲区是*连续的*.因此,`&str [str.size() - 1] ==&str [str.size()] - 1`必须为真(假设`length()`至少为1).如果不是,那么缓冲区将不是连续的. (2认同)

Mr.*_*C64 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);
Run Code Online (Sandbox Code Playgroud)

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

  • 我也会选择这个解决方案.但令人不满的是,这需要完全不必要地分配一个额外的角色.为什么规范只能使空终止可写? (2认同)

T.C*_*.C. 10

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

否则,返回对charT具有value 的类型对象的引用charT(),其中将对象修改为除了charT() 导致未定义行为之外的任何值.

  • @MM这隐藏在`data()`的规范中. (2认同)

Win*_*mer 5

我想n3092不再是现在了,但这就是我所拥有的.第21.4.5节允许访问单个元素.它需要pos <= size().如果pos <size()则获得实际元素,否则(即如果pos == size())则获得不可修改的引用.

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

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