作为参数传递的std :: string的生命周期

时间:2012-06-03 15:29:41

标签: c++ stl

我想确定我理解正确。在c ++函数下面有三个实例 将创建std :: string:

  • 一个用于调用者()中的s1,通过我认为称为赋值构造函数
  • 一个用于callee()函数的s2参数,通过它的复制构造函数
  • 一个用于s3通过其复制构造函数

我说错了吗?如果是这样,所有三个实例都会在超出范围时被清理干净?我不是真的在问这个代码是不是很好,只要我的理解是正确的。

void caller(void) {
    std::string s1 = "hi";
    callee(s1);
}

void callee(std::string s2) {
    std::string s3 = s2;
}

2 个答案:

答案 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
}