我想确定我理解正确。在c ++函数下面有三个实例 将创建std :: string:
我说错了吗?如果是这样,所有三个实例都会在超出范围时被清理干净?我不是真的在问这个代码是不是很好,只要我的理解是正确的。
void caller(void) {
std::string s1 = "hi";
callee(s1);
}
void callee(std::string s2) {
std::string s3 = s2;
}
答案 0 :(得分:3)
不要假设副本是在似乎制作的任何地方制作的。在实践中,复制省略的发生频率超出了您的想象。编译器可以自由地优化掉额外的副本,即使副本有副作用:
void caller(void) {
std::string s1 = "hi";
//theoretically, s1 is copied here
//in practice, the compiler will optimize the call away
functionCallee(s1);
}
void callee(std::string s2) {
//although s2 is passed by value, it's probably no copy was created
//most likely, it's exactly the same as s1 from the calling context
std::string s3 = s2;
}
此外,如果方法是内联的并且编译器检测不到任何副作用,则甚至不会创建字符串 。
答案 1 :(得分:2)
你几乎是正确的。
可以创建三个或四个字符串(取决于是否省略了s1
的构造),并且在每种情况下都调用构造函数来构造它们。尽管有外表,但没有任何调用任何操作员。
void caller(void) {
//A temporary std::string is constructed with the
//basic_string(const CharT* s, const Allocator& alloc = Allocator())
//constructor.
//(In the call, `s` is initialized to point to the first element of "hi".)
//This temporary is then move constructed in to s1.
//The move constructor is
//basic_string(basic_string&& other)
//This move construction may be elided.
std::string s1 = "hi"; //At the end of the full expression (ie, at the semicolon)
//the lifetime of the temporary string ends (unless
//the construction of s1 is elided, in which
//case the temporary becomes s1, and its lifetime ends
//with s1).
//s2 is copy constructed from s1
//The copy constructor is
//basic_string(const basic_string& other)
callee(s1);
//the lifetime of s1 ends
}
void callee(std::string s2) {
//s3 is copy constructed from s2
std::string s3 = s2;
//the lifetime of s3 ends
//the lifetime of s2 ends
}