首页 > 编程语言 >c++ 关于函数返回值问题

c++ 关于函数返回值问题

时间:2023-06-06 15:58:50浏览次数:36  
标签:返回 副本 函数 对象 c++ 编译器 返回值 优化

c++中,当函数返回基本元素时,一般不会产生异常情况。但是当返回引用或指针时,即不使用值传递而是引用或指针传递来实现,那么需注意:

不能返回函数内部的局部变量指针或引用。因为局部变量是在栈上,当离开函数作用域时,其内容会失效,相应的返回的指针或引用指向的内容就没有意义了。

不能返回函数内部new或malloc的堆内存的引用。因为虽然得到的引用有实际意义,但是因为在主函数中没有指针再指向该块堆内存,那么这块内存便无法释放,造成内存泄漏。

 

当函数返回值类型是类时,即通过值传递返回类对象,那么其是可以返回函数内部栈上创建的对象的。因为在返回类对象时,函数在返回时会发生一次拷贝,返回的其实是栈对象的拷贝副本,这个副本的内容不会因为离开函数作用域而失效,因此返回栈对象是可行的,如下例所示:

#include <iostream>

class MyClass {
public:
    MyClass(int value) : data(value) {}

    int getData() const {
        return data;
    }

private:
    int data;
};

MyClass createObject() {
    MyClass obj(42);  // 在函数内部创建栈对象
    return obj;  // 直接返回对象
}

int main() {
    MyClass newObj = createObject();  // 接收返回的对象副本
    std::cout << newObj.getData() << std::endl;  // 输出: 42

    return 0;
}

在上述示例中,返回的副本对象仍然是在栈上而不是堆上。

当函数返回一个对象时,C++编译器通常会优化为执行返回值优化(Return Value Optimization,RVO)或命名返回值优化(Named Return Value Optimization,NRVO)。这些优化技术可以避免不必要的拷贝操作,将函数内部创建的对象直接放置在函数调用方的目标位置上。

在示例代码中,createObject函数内部创建的对象obj在函数返回时被直接放置在newObj对象的位置上,而不是在堆上创建一个新的对象。因此,返回的副本对象仍然是在栈上。

需要注意的是,优化行为可能会因编译器、编译器设置和编译器优化级别而有所不同。在一些情况下,即使没有启用优化,返回的副本对象也可能仍然是在栈上而不是堆上。因此,具体的优化行为可能会因编译器和上下文而有所不同。

综上所述,返回的副本对象通常仍然是在栈上而不是堆上,但具体的优化行为可能因编译器和上下文而有所不同。

 

原创内容,个人思考仅供参考,若有错误请联系作者指出

标签:返回,副本,函数,对象,c++,编译器,返回值,优化
From: https://www.cnblogs.com/Explosion556/p/17460759.html

相关文章

  • mysql-窗口函数
    转:https://zhuanlan.zhihu.com/p/456560406什么是窗口--窗口对于group分组和聚合函数等,窗口是固定的,就是每一组,比如想知道每个学生的平均成绩,指定的组就是每个学生的id,聚合函数在这个id划定的窗口内对所有记录进行计算。这是静态窗口,窗口内的记录相互关联,窗口外的记录彼此......
  • [c++实践]关于标准库中字符串的高效处理
    [c++实践]关于标准库中字符串的高效处理无论什么程序,都需要大量的使用字符串,c++标准库提供了std::string对字符串进行处理。熟悉std::string实现逻辑的都知道,std::string库比较耗时的操作主要在内存的分配与字符串的拼接。因为内存分配实际上还是使用的malloc,但是在多线程......
  • C++ 中的 String 类
     C++标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。我们将学习C++标准库中的这个类,现在让我们先来看看下面这个实例:现在您可能还无法透彻地理解这个实例,因为到目前为止我们还没有讨论类和对象。所以现在您可以只是粗略地看下这个实例,等理解了......
  • C++中的显式构造函数
      有如下一个简单的复数类:classClxComplex{public:ClxComplex(doubledReal=0.0,doubledImage=0.0){m_dReal=dReal;dImage=dImage;}doubleGetReal()const{returnm_dReal;}doubleGetImage()const{retu......
  • C++类构造函数、拷贝构造函数、复制构造函数、复制构造函数、构造函数显示调用和隐式
    一、构造函数是干什么的 1.2.{3.public:4.//类Counter的构造函数5.//特点:以类名作为函数名,无返回类型6.Counter()7.{8.0;9.}10.private:11.//数据成员12.intm_value;13.}      该类对......
  • C++智能指针的原理和实现
    一、智能指针起因在C++中,动态内存的管理是由程序员自己申请和释放的,用一对运算符完成:new和delete。new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针;delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。使用堆内存是非常频繁的操作,容易造成......
  • 在前端中函数柯里化的妙用~
    前言:在使用它之前我们需要先了解什么是柯里化?所谓的柯里化不过就是将多个固定的参数生成一个新动态的调用函数,这句话看起来有点绕!但是我们理解清楚后就不会有这种感觉~在某些场景中我的执行函数是固定参数才会执行的,但是这些参数取数又不是一次性的时候你会怎么处理?我们一个函......
  • Python Exit——如何在Python中使用Exit函数来停止程序
    Python中的函数exit()用于退出或终止当前运行的脚本或程序。您可以使用它随时停止程序的执行。当exit()函数被调用时,程序会立即停止运行并退出。该函数的语法exit()是: exit([status])这里,status是一个可选参数,表示程序的退出状态。退出状态是一个整数值,表示程序终止的原因。按......
  • C++ 中的信号的处理
    C++ 信号处理信号是由操作系统传给进程的中断,会提早终止一个程序。在UNIX、LINUX、MacOSX或Windows系统上,可以通过按Ctrl+C产生中断。有些信号不能被程序捕获,但是下表所列信号可以在程序中捕获,并可以基于信号采取适当的动作。这些信号是定义在C++头文件<csignal>中。......
  • C#调用C++dll
    C#调用C++dll的方法和步骤其他分享涉及到的概念和方法对于像我这样比较菜的选手看起来比较费劲并且很难抓住重点,这里我总结了一段时间的研究成果供初学者救济之用,简单明了。工具/原料 VS2008方法/步骤 新建项目->VisualC++->Win32项目 MyDLL注意:C++编写的dll一般是不能直接拿来......