c ++方法链接返回值不起作用

时间:2017-10-27 05:33:47

标签: c++ scope

我在很长一段时间后使用cpp进行opengl项目。我面临的问题与cpp特别是与opengl有关。下面的两个代码片段有什么区别?

// this works
std::string tmp = FileIO::read("vertex_shader");
const char *vertexShaderSource = tmp.c_str();
std::cout<< vertexShaderSource <<std::endl; //shows proper value

//but this doesn't work 
const char *vertexShaderSource = FileIO::read("vertex_shader").c_str();
std::cout<< vertexShaderSource <<std::endl; //shows garbage value

//FileIO::read() returns a string value

我有点困惑为什么第一个工作但第二个显示垃圾?我错过了什么吗?

请任何cpp专家告诉我第二个代码片段有什么问题以及为什么它不起作用。提前谢谢,

3 个答案:

答案 0 :(得分:3)

假设FileIO::read()按值返回std::string,那么当您执行

FileIO::read("vertex_shader").c_str()

std::string返回的FileIO::read对象是临时。一旦调用了它的c_str()函数,对象就会超出范围并被破坏,为你留下一个指向不再存在的字符串的指针。

取消引用此指针(当您尝试打印字符串时会发生这种情况)会导致undefined behavior

答案 1 :(得分:3)

我认为FileIO::read按值返回,然后FileIO::read("vertex_shader")会返回temporary std::string,它将在完整表达式后被销毁。在那之后vertexShaderSource成为一个悬垂的指针,任何取消引用都会导致UB。即。

const char *vertexShaderSource = FileIO::read("vertex_shader").c_str();

// vertexShaderSource becomes dangled from here
std::cout<< vertexShaderSource <<std::endl; // UB

如果使用命名变量tmp作为第一个代码示例显示,tmp将不会被销毁,直到超出其定义的范围;那么代码很好。

答案 2 :(得分:2)

您遇到的问题与变量的生命周期有关。 var rootUrl = new UriBuilder("http", "example.com", 50000).Uri.ToString().TrimEnd('/'); 会返回保存字符串的FileIO::read

在第一种情况下,您正在复制(实际上由于RVO不能复制任何副本)返回值到变量,然后您将获得指向字符串的char数组的指针。因此,指针指向的内存由std::string变量拥有。

在第二种情况下,您正在检索指向由tmp函数返回的临时字符串所拥有的char数组的指针。这为您提供了临时拥有的内存地址。 在该语句完成之后,临时被破坏以及它拥有的所有内存,其中包括您检索并存储在read中的指针指向的char数组。