3

我想确保我理解正确。在下面的 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;
}
4

2 回答 2

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;
}

此外,如果方法是内联的并且编译器检测到没有出现副作用,则甚至可能不会创建字符串。

于 2012-06-03T15:35:14.940 回答
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
}
于 2012-06-03T15:49:00.767 回答