C++返回值为对象时复制构造函数不执行怎么破

  先说点背景知识,调用复制构造函数的三种情况:

  1.当用类一个对象去初始化另一个对象时。

  2.如果函数形参是类对象。

  3.如果函数返回值是类对象,函数执行完成返回调用时。

  在辅导学生上机时,有同学第3点提出异议。有教材上的例题为证:

#include <iostream>
using namespace std;
class Point     //Point 类的定义
{
public:
    Point(int xx=0, int yy=0)
    {
        x = xx;    //构造函数,内联
        y = yy;
    }
    Point(const Point& p); //复制构造函数
    void setX(int xx)
    {
        x=xx;
    }
    void setY(int yy)
    {
        y=yy;
    }
    int getX() const
    {
        return x;    //常函数(第5章)
    }
    int getY() const
    {
        return y;    //常函数(第5章)
    }
private:
    int x, y; //私有数据
};
//成员函数的实现
Point::Point (const Point& p)
{
    x = p.x;
    y = p.y;
    cout << "Calling the copy constructor " << endl;
}

//形参为Point类对象的函数
void fun1(Point p)
{
    cout << p.getX() << endl;
}
//返回值为Point类对象的函数
Point fun2()
{
    Point a(1, 2);
    return a;
}

//主程序
int main()
{
    Point a(4, 5);	//第一个对象A
    Point b = a;	//情况一,用A初始化B。第一次调用复制构造函数
    cout << b.getX() << endl;
    fun1(b);	//情况二,对象B作为fun1的实参。第二次调用复制构造函数
    b = fun2();	//情况三,函数的返回值是类对象,函数返回时调用复制构造函数
    cout << b.getX() << endl;
    return 0;
}

  证据是,在CodeBlocks中,运行结果是:

  

  而不是期望的:
  

  显然,第3种情况下,复制构造函数没有被执行。

  确定问题后,我知道道理是对的,看过的几本书,厚的、薄的,都是这么写的。会不会是编译器的差别?CodeBlocks用的是gcc。gcc开源,跟标准的变化跟得紧,莫不是第3种情况已经成了老黄历,而各种书来不及变?

  我让她到VC++6.0中运行。一会儿她的反馈,在VC++6.0中复制构造函数执行了。

  真相明白了。

  这个问题需要有个交待。

  回家后再翻各种书,无果。网络搜索,CSDN上有个贴子《函数返回值是对象,是调用了拷贝构造函数?》,其中大家给的结论,是gcc做了优化,返回值为对象时,不再产生临时对象,因而不再调用复制构造函数。

  看来不是标准发生变化。

  那如果一定想要让这个构造函数执行呢?只需让忽略gcc不要搞这个优化就行了。贴子中给了个线索,在新浪博客《命名返回值优化》。文章称通过搜索知道“这是一个称为命名返回值优化的问题,而且g++的这个编译优化竟然没有直接的关闭方法给出解决办法”。作者是用命令行工作的,他后来解决的办法,是在编译命令中加上“-fno-elide-constructors”参数,例g++ -fno-elide-constructors testReturn.cpp 。

  我的学生还处在用IDE的阶段。本文的价值来了,如何在CodeBlocks下也忽略这个优化项呢?

  在CodeBlocks中,通过菜单依次选:settings->Compiler...,在Global compiler settings部分,选择Other options,在文本框中写入“-fno-elide-constructors”,如图,然后就可以ok啦。

  

  然后,如同苦难的公主终于和王子过上了幸福的生活一样,期望的结果有了。

  

  “-fno-elide-constructors”选项起了作用,有图为证。下面中加上这个参数后,编译完看到的提示信息:

  

时间: 2024-08-06 11:34:23

C++返回值为对象时复制构造函数不执行怎么破的相关文章

[转]C++函数返回值为对象时,构造析构函数的执行细节

看如下代码: 复制代码代码如下: #include<iostream>class TestConstructor{public:    TestConstructor()    {        std::cout<<"TestConstructor()"<<std::endl;    }    ~TestConstructor()    {        std::cout<<"~TestConstructor()"

以函数返回值做参数时,函数调用的顺序

环境:vs2013 在下面的代码中 1 //类似于下面的代码 2 3 foo(char*,char*,char*); 4 5 char* str ="A#B#C"; 6 7 foo(strtok(str,"#"),strtok(NULL,"#"),strtok(NULL,"#")); 预计让函数foo得到("A","B","C")的参数,程序编译的时候没问题,但是运行

带有参数和返回值的对象方法

# 按要求设计一个计算器类 # 属性: 无. 功能: 1) 返回派的值. 2) 计算一个整数的平方. 3) 计算两个整数的和. // 按要求设计计算器类 // 类的声明 #import <Foundation/Foundation.h> @interface Calculator : NSObject // 没有属性不用写大括号{} - (double) pi; - (int) square:(int)num; // 关于方法名的说明见下面 - (int) sumOfNum1:(int)num

zbb20170928 解决springmvc在单纯返回一个字符串对象时所出现的乱码情况

解决springmvc在单纯返回一个字符串对象时所出现的乱码情况 使 用springmvc框架开发了这么长时间,之前都是直接返回jsp页面,乱码情况都是通过配置和手动编解码来解决,但是今天突然返回一段单纯的字符串 时,发现中文乱码情况解决不了了,下面就给各位分享一下如何解决返回字符串时出现的乱码情况(无需实验,直接使用即可). 之前我们都是通过在springmvc的核心配置文件中配置视图解析器来返回指定的页面,将数据通过Model对象渲染页面,最后响应给用户,但是这种方式我们是通过在web.xm

方法阻塞,方法一直阻塞,意味着这个程序卡在这里,一直不向下运行。知道这个阻塞方法执行完毕,有返回值。程序才继续向下执行

方法阻塞,方法一直阻塞,意味着这个程序卡在这里,一直不向下运行.知道这个阻塞方法执行完毕,有返回值.程序才继续向下执行. while (true) { // 当注册事件到达时,方法返回,否则该方法会一直阻塞 selector.select();  //这里将一直阻塞,程序不会向下执行.直到这个方法执行完,有返回值后 2.// 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 NIO SERVER NIO SERVERpackage com.anders.selecto

Mybatis select返回值为map时,选取表字段的两列作为key,value

项目需要从ibatis升级到MyBatis,dao中有一个方法返回Map类型,具体是查询语句查询两个字段,将结果列表字段A的值作为key字段B的值作为value存入Map中作为结果返回: ibatis中Dao继承SqlMapClientDaoSupport类的queryForMap(String statement, Object param, String key, String value)方法可直接实现: MyBatis的SqlSession中只有selectMap(String stat

返回值过长时被nginx截断的解决办法

今天在写接口时碰到了这个问题,返回json格式的数据,但是被截断了经过排查,才发现是数据过大超出缓冲区最大容量,而将数据写入临时文件时又没有权限,所以再返回时,超出缓冲区的数据将丢失解决方法:给fastcgi_temp 目录赋读写权限?在nginx配置中的解释 1 Syntax: fastcgi_buffers number size; 2 Default: fastcgi_buffers 8 4k|8k; 3 Context: http, server, location 4 Sets the

对象个数以及构造函数次序

当创建派生类对象时,构造函数的执行次序是 基类构造函数 对象成员构造函数 派生类构造函数,不信看代码 #include <iostream> using namespace std; class A { public: A() { cout<<"A"<<endl; } }; class C { public:C() { cout<<"C"<<endl; } }; class B:public A { pub

java.lang.Object.hashCode()的返回值到底是不是对象内存地址?

刚学Java的时候我也有过这种怀疑,但一直没有验证:最近在OSCHINA上看到有人在回答问题时也这么说,于是萌生了一探究竟的想法--java.lang.Object.hashCode()的返回值到底是不是对象内存地址? (顺带回顾一下JNI) hashCode契约 说到这个问题,大家的第一反应一定和我一样--去查Object.hashCode的源码,但翻开源码,看到的却是这样的(Oracle JDK 8): /** * Returns a hash code value for the obje