为什么 --string::end() 可以编译,而 --string.size() 不能编译?
Why does --string::end() compile but --string.size() does not?
代码
std::string str{ "foo" };
auto lastCharIndex{ --str.size() };
创建编译器错误lvalue required as decrement operand
但
auto lastCharIterator{ --str.end() };
不。这是为什么呢?
>string::size
按值返回标量类型(某种整数),并且 prvalues 上不允许使用内置前缀 ---
表达式。相比之下,对于重载运算符(在用户定义类型上),它们本质上只是函数,则不适用此类限制。因此,是否允许--str.end()
取决于string::iterator
是用户定义类型(某种类类型)还是标量类型(例如指针)。但是,这没有指定,甚至可能因优化设置而异。
我想补充一点,您可以自定义用户定义的成员函数,例如通过左值和右值引用调用时行为不同的++
。例如,可以定义一个自定义iterator
类,以防止在临时上调用修改成员函数。为此,需要使用引用限定符。
class iterator {
public:
iterator operator++() & { // for lvalues
std::cout << "incrementing...n";
}
iterator operator++() && = delete; // for rvalues
};
使用这些限定符,您仍然允许修改左值:
iterator it = ...;
++it; // totally fine
但是,您现在可以防止修改临时项,从而生成与内置类型(如size_t
)更一致的用户定义类。
++(iterator{}); // ERROR
现场示例在这里
我不确定标准对std::string
迭代器类型有什么看法,但原则上,你可以为自己的迭代器和其他类这样做,只要你认为修改临时总是一个错误。
基本类型算术类型的递减(和递增)运算符的操作数必须是左值。std::string::size
返回整数类型的值(即不是引用),因此函数调用str.size()
是一个 prvalue。prvalues 不是左值,因此--str.size()
格式不正确。
类类型的递减(和递增)运算符重载的操作数可以在右值上调用,除非重载是左值引用限定的。如果--str.end()
格式正确,那么我们可以推断迭代器是一个类类型(指针将是不是类类型的迭代器类型的一个例子),并且递减运算符重载确实没有左值引用限定符。据我所知,标准容器迭代器的成员函数是否是 ref 限定的,这是未指定的。
附言:同样适用于(复合)赋值运算符:赋值的left 手动操作数也必须是左值(除非它是具有非左值引用限定的重载的类类型)。事实上,这就是 l 值中">l"的起源。
- 使用 MINGW gcc 编译时,不会为 std::string 调用重载的新运算符
- 如何在编译时解析静态常量 std::string?
- C++ string.substr 的编译方式不同
- 使用 string::p op_back() 的编译错误
- 涉及"std::string"的编译会导致 Windows 错误状态
- std::string 最终会成为我们的编译时字符串吗?
- 编译错误"String does not name a type"
- 为什么 --string::end() 可以编译,而 --string.size() 不能编译?
- 编译代码时麻烦 - strncpy char*和string
- 为什么 clang ++ 编译代码而 clang -x C++ 失败?ncurses with std::string.
- 编译错误与 boost/algorithm/string/trim.hpp.
- 为什么 stack<const string> 不能用 g++ 编译?
- 为什么 std::string::max_size 不是编译时常量?
- std::find on std::vector< std::string > 在 Visual C++ 2008 中无法编译?
- 与常量 std::string 的向量相关的编译失败
- 模板化运算符 string() 在临时对象时无法编译
- C++ 入门第 9 章没有编译:"useConvs.cc:50:19:错误:重载的调用"stod(std::string&)"是不明确的"
- c ++比较std::string将无法工作,如果我不使用Code::Blocks但cygwin编译
- OS X Lion 上的 libplist 编译错误:找不到 string.h
- 为什么Visual Studio需要<string>编译,而代码块不需要?