c++ - 返回对象时编译器做了什么

标签 c++

我有以下名为 DATA 的类。

enum DATATYPE{DATATYPE_CONSTANT=0, DATATYPE_NUMBER,DATATYPE_STRING, DATATYPE_MATRIX, DATATYPE_OBJECT};

struct DATA //A Data container for the variable
{
    DATA(DATATYPE type,int row=0,int col=0)
    {
        m_str=0;m_number=0;

        m_DataType=type;

        if(type==DATATYPE_NUMBER) m_number=new double;
        if(type==DATATYPE_STRING) m_str=new string("");

        cout<<"In constructor"<<endl;
        //if(type==DATATYPE_MATRIX) m_matrix= new MatrixXd(row,col);
    }
    ~DATA()
    {
        if(m_str) m_str->clear();
        if(m_number) {delete m_number; m_number=0;}

        std::cout<<"In Destructor"<<std::endl;
        //if(m_matrix) {delete m_matrix; m_matrix=0;}
    }

    DATA(const DATA& other)
    {
        m_number=other.m_number;
        m_str=other.m_str;
        m_DataType=other.m_DataType;

        cout<<"In copy constructor"<<endl;
    }

    DATA& operator=(const DATA& other)
    {
        m_number=other.m_number;
        m_str=other.m_str;
        m_DataType=other.m_DataType;

        cout<<"In operator="<<endl;

        return *this;
    }

    DATATYPE GetType()
    {
        return m_DataType;
    }

    double* GetNumber()
    {
        return m_number;
    }

    void SetNumber(const double& val){*m_number=val;}


    string* GetString()
    {
        return m_str;
    }

private:
    DATATYPE m_DataType;
    string* m_str;
     //MatrixXd* m_matrix;
    double* m_number;
};

我有以下测试:

DATA GetData();

int main()
{
    cout<<"Before GetData call"<<endl;
    DATA dat=GetData();
    //DATA dat2=dat;
    cout<<*(dat.GetNumber())<<endl;
    cout<<"After Get Data call"<<endl;

    cout << "Exiting main" << endl;
    return 0;
}


DATA GetData()
{
    cout<<"In Get Data"<<endl;
    DATA ret(DATATYPE_NUMBER);
    double d=5;
    ret.SetNumber(d);
    cout<<"Exiting GetData"<<endl;
    return ret;
}

运行测试后输出为:

Before GetData call

In Get Data

In constructor

Exiting GetData

5

After Get Data call

Exiting main

In Destructor

我有以下问题:

  1. 当我调用 DATA dat=GetData(); 时,它既不调用构造函数、复制构造函数也不调用等于运算符。 dat对象是如何构造的。另外,编译器从 GetData 返回时究竟做了什么?

  2. 对于DATA 结构,或者一般的聚合数据类型,用new 初始化成员变量总是一个好主意吗?当我初始化 say DATA *d=new DATA(DATATYPE_NUMBER) 时,成员变量会发生什么?内存泄漏是否更容易出错?

最佳答案

问题一

当我调用 DATA dat=GetData(); 时,它既不调用构造函数、复制构造函数也不调用等于运算符。 dat对象是如何构造的。另外,从 GetData 返回时,编译器究竟做了什么?

回答 这是返回值优化 (RVO) 的结果。您可以阅读更多关于它们的信息 here .

在 g++ 中,您可以使用标志 -fno-elide-constructors 禁用 RVO。如果您对代码执行此操作,您将看到来自复制构造函数的消息。

问题二

对于 DATA 结构,或者一般的聚合数据类型,用 new 初始化成员变量总是一个好主意吗?当我初始化 say DATA *d=new DATA(DATATYPE_NUMBER) 时,成员变量会发生什么?内存泄漏是否更容易出错?

回答

里面有3个问题。

回答 2.1

该问题的答案是“取决于您的应用程序”。对于某些人来说,将对象作为成员数据是有意义的,而对于其他人来说,将对象指针作为成员数据是有意义的。当你使用指向对象的指针时,你必须遵循 Rule of Three , 已成为 Rule of Five in C++11 .

回答 2.2

成员变量的初始化就像您使用它们一样:

Data d = DATA(DATATYPE_NUMBER);

回答 2.3

使用动态内存有好处,但也有缺点。任何时候使用动态内存分配,都会进入更容易出错的代码。你必须担心它潜在的​​不良副作用:

  1. 悬挂指针。
  2. 丢失指针。
  3. 访问超出分配的内存。

关于c++ - 返回对象时编译器做了什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24947323/

相关文章:

c++ - 来自另一个类的对象的类 vector

c++ - Windows VK_ 常量是如何声明的?

c++ - 带线性探测的字符串散列

c++ - 模板参数错误,C++

c++ - 如何正确处理信号,以便 gperftools CPU 分析器仍然有效?

c++ - Qt4 QSettings 读取具有多个值的数组

C++ 指针 vector 和引用变量

使用多线程的无序映射的 C++ 填充

c++ - C++ 纯虚函数调用的性能可变性

c++ - 使用 vim 检测 C++ 标准头文件的文件类型