关于字符串对象寿命的一些问题

时间:2015-05-21 17:32:53

标签: c++ string

在这里尝试更多地理解c ++字符串。这里的编译器是g ++ 4.7.3。

问题1:在下面的代码片段中,编译器是否足够智能以在函数末尾释放用户数据(在堆中,由s隐式指向)?我认为答案是肯定的,只是想确认一下。

void dummy() {
    string s;
    s.append("hello");
    //more append
}

问题2:在下面的代码片段中,当函数返回时,编译器不会释放s指向的用户数据。是对的吗?如果是这样,编译器可以在调用者中释放用户数据(如果调用者函数本身不返回字符串对象)。

string dummy() {
    string s;
    s.append("hello");
    //more append
    return s;
}
//some caller
string s1 = dummy();

2 个答案:

答案 0 :(得分:3)

在问题1中,是的,当函数dummy结束时,将释放变量s的内存,因为这是s变量的封闭范围。

在问题2中,编译器可能会使用return value optimization来避免将内存从s1复制到s,因为 $scope.gridOptions.onRegisterApi = function(gridApi){ //set gridApi on scope $scope.gridApi = gridApi; gridApi.selection.on.rowSelectionChanged($scope,function(row){ var msg = 'row selected ' + row.isSelected; $log.log(msg); }); gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){ var msg = 'rows changed ' + rows.length; $log.log(msg); }); }; 即将超出范围

答案 1 :(得分:3)

  

问题1:在下面的代码片段中,编译器是否足够聪明以在函数末尾释放用户数据(在堆中,由s隐式指向)?

是的,它是必需的。在函数作用域的末尾,将调用字符串的析构函数,这将释放分配的内存。

对象s被称为具有“自动存储持续时间”,并且标准通过§3.7.3/ 1描述:

  

显式声明寄存器或未显式声明为static或extern的块范围变量具有自动存储持续时间。这些实体的存储将持续到创建它们的块退出。

  

问题2:在下面的代码片段中,编译器在函数返回时不会释放s指向的用户数据。是对的吗?如果是这样,编译器可以在调用者中释放用户数据(如果调用者函数本身不返回字符串对象)。

编译器可以使用所谓的RVO(返回值优化)来删除副本。具体而言,标准词语如下,§12.8/ 31:

  

在下列情况下(可以合并以消除多份副本),允许复制/移动操作(称为复制省略)的省略:

     
      
  • 在具有类返回类型的函数的return语句中,当表达式是具有与函数相同的cv-非限定类型的非易失性自动对象(函数或catch子句参数除外)的名称时通过将自动对象直接构造到函数的返回值
  • 中,可以省略复制/移动操作   
  • 在throw-expression(5.17)中,当操作数是非易失性自动对象(函数或catch子句参数除外)的名称时,其范围不会超出最内层封闭的末尾 - 块(如果有的话),通过将自动对象直接构造到异常对象中,可以省略从操作数到异常对象(15.1)的复制/移动操作
  •   
  • 当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过直接构造临时对象来省略复制/移动操作进入省略的复制/移动的目标
  •   
  • 当异常处理程序的异常声明(第15条)声明一个相同类型的对象(cv-qualification除外)作为异常对象(15.1)时,可以通过处理异常声明来省略复制操作如果除了为exception-declaration声明的对象执行构造函数和析构函数之外,程序的含义将保持不变,则作为异常对象的别名。 [注意:不能从异常对象移动,因为它始终是左值。 -endnote]
  •