在C和C++(以及其他几种语言)中,字符和字符串常量中的水平制表符(ASCII代码9)以转义形式表示为'\t'和"\t".不过,我经常键入字符串文字例如在转义字符制表"A B"(存在王全凯一个TAB A和B),以及至少铛++似乎不打扰-字符串似乎等同于"A\tB".我更喜欢未转义的版本,因为长缩进的多行字符串在源代码中更易读.
现在我问自己这在C和C++中是否通常是合法的,或者只是由我的编译器支持.非字符表制表符在字符和字符串常量中的可移植性如何?
令人惊讶的是,我无法找到这个看似简单的问题的答案,无论是Google还是stackoverflow(我刚发现这个含糊不清的相关问题).
一段时间以来,我一直想知道std::string的substr(pos, len)方法设计背后的基本原理。这对我来说仍然没有意义,所以我决定请教专家。std::out_of_range如果pos参数超过字符串长度加一,该函数将引发异常。这有时会很不方便(甚至很烦人),但我真正关心的是一致性和最小惊喜原则。事实证明,pos+len子串的“结束”位置允许超过字符串长度加一。一开始就不允许这样做,但在结束时不允许这样做,这对我来说是不一致的。允许它结束我暗示了解释
返回位置处的所有字符 pos <= i < pos+len
但是,那么我希望该函数为pos超过字符串长度的值返回一个空字符串,而不是抛出异常。作为旁注,根据这种解释,允许负值甚至是明智的pos(假设它具有有符号类型)。
这给我留下了以下问题:
std::string是不是空值终止,而是跟踪字符串的长度。如果这是真正的原因,那么我个人认为这是一个非常糟糕的原因。substr未来的行为?我想不会,因为默默地破坏现有代码肯定比忍受这种扭曲更糟糕......?这个问题表明std::initializer_list<int>::const_iterator类型只是一个普通的int const*指针,但是这个答案(对于同一个问题)引用的标准的措辞听起来更像是一个建议,而不是对我的保证.
在我的代码中,问题发生如下:我有一个处理a的子范围的函数initializer_list,在不同的情况下,我重用传递单个元素的便捷函数的代码(作为单元素范围):
void doStuff(int const* begin, int const* end)
{ ... do stuff ... }
// main use; in the real code, 'init' is a parameter of a function
std::initializer_list<int> init({1, 2, 3, 4, 5});
doStuff(init.begin() + 1, init.end());
// alternative use of doStuff, relies on the pointer assumption
int x = 6;
doStuff(&x, (&x) + 1);
}
Run Code Online (Sandbox Code Playgroud)
这种结构依赖于迭代器确实是指针的事实.它至少适用于我的clang ++ 3.9编译器.我可以依靠它来始终工作,即指针假设是否可移植?保证便携?或者我应该将参数类型更改doStuff为模板参数,以确保安全吗?
template <typename Iterator>
void doStuff(Iterator begin, Iterator …Run Code Online (Sandbox Code Playgroud)