为什么对象的生命周期"是子对象的完整对象"返回子对象时扩展?

时间:2015-02-11 06:02:42

标签: c++ c++11 reference temporary-objects

我正在研究绑定到const &时临时生命的延长,我想了解以下情况:

#include <string>
#include <iostream>

char const * foo()
{
    std::string s("tmp");
    return s.c_str();
}

int main()
{
    char const * const & p = foo();

    // Why is the lifetime of the std::string extended in the following line,
    // rather than just the lifetime of the char* itself?
    std::cout << p; // This prints 'tmp' in VS2013
}

如上所述,在Visual Studio 2013中,代码构建时没有错误,控制台会打印tmp

这对我来说似乎很奇怪,因为生命周期被扩展的对象是被调用函数本地对象的子对象,当退出该函数时会被销毁。堆栈上没有std::string作为返回值,编译器在编译main函数时可以扩展其生存期 - 只有char *返回值,其值生命可以延长,但这将是一个悬垂的指针。

但显然,生命周期正在延长!

我发现的最接近的问题是:Does "T const&t = C().a;" lengthen the lifetime of "a"? ...但是,在这个问题中,代码B const& b = A().b;引用了调用内堆栈上的完整对象A函数,以便对象可用以延长其生命周期。

如上所述,在我看来,在我的代码示例中应该延长其生命周期的对象是char *,而不是char * points的字符串。 (也就是说,我认为返回值,只是char *的大小,本身会延长其生命周期,但它会成为一个悬空指针。)

我不明白如何在上面的示例代码中扩展std::string的生命周期。有人可以解释为什么这满足std::string生命延长char const * const &的生命周期的标准,而不仅仅是延长char *的生命周期?< / p>

1 个答案:

答案 0 :(得分:4)

如何跟踪对象的构造函数和析构函数

#include <string>
#include <iostream>

class string_like: public std::string {

public:
  string_like(const char* str): std::string (str) {
    std::cout << "string_like() : \n";
}
  ~string_like() {
    std::cout << "~string_like(): \n";
}
};

char const * foo()
{
  std::cout << "in foo(){} : \n" ;

  string_like  s("tmp");

  std::cout << "leaving foo(){}" << "\n";
  return s.c_str();
}


int main()
{
  std::cout << "begin main()\n";
  std::cout << "calling foo() :" << "\n";
  char const * const & p = foo();
  std::cout << "after calling foo() :\n";
  std::cout << "still in main\n" ;
  std::cout << p << "\n"; // print using g++
  std::cout << "leave main()\n";

}

我得到了g ++的以下输出:

begin main()
calling foo() :
in foo(){} : 
string_like() :
leaving foo(){}
~string_like():  object is destroyed here
after calling foo() :
still in main
tmp    
leave main()