通过引用传递数据来构建它

时间:2016-02-01 15:49:29

标签: c++ pointers pass-by-reference

在C ++下我经常遇到错误。 假设我有以下类:

class ClassData
{
public:
    ClassData() { a=-1; }

public:
    int a;
};

class MyClass
{
public:
    MyClass() { m_classData = 0; }
    MyClass(ClassData* classData) { m_classData = new ClassData(*classData); m_classData->a=1; }

    inline bool getClassData(ClassData* classData) {
        if (m_classData) { classData = m_classData; return true; }
        else return false;
    }

private:
    ClassData* m_classData;
};

现在主要是我运行这个测试代码:

ClassData cdata;
MyClass* m_myClass = new MyClass(&cdata);

int value = 0;
ClassData classData;
if (m_myClass->getClassData(&classData))
    value = classData.a; 

如果代码运行,value等于-1(而不是1)。

第一个问题:为什么我无法在ClassData中引用MyClass?虽然我正在考虑拥有ClassData m_myClass的{​​{1}}对象(如果它是公开的那样做m_myClass->m_classData),实际上我正在呼叫成员{{1在本地a对象上。

我在想,原因是我无法更改本地变量地址,但如果我将代码更改为:

ClassData

我的程序崩溃了。

第二个问题:管理这种情况的正确方法是什么?问题是在程序主函数中还是在定义ClassData* classData=0; if (m_myClass->getClassData(classData)) value = classData->a; 的方式中为错误提供了空间?

2 个答案:

答案 0 :(得分:1)

下面:

bool getClassData(ClassData* classData) {
  if (m_classData) { classData = m_classData; return true; }
  else return false;
}

请注意classData本地变量。它在函数终止时死掉,所以函数除了报告m_classData是否为空之外什么都不做。

所以在第一种情况下:

ClassData classData; // <-- classData.a is -1
if (m_myClass->getClassData(&classData))
  value = classData.a; // <-- classData.a is still -1

在第二种情况下:

ClassData* classData=0;      // classData is null
if (m_myClass->getClassData(classData))
    value = classData->a;    // classData is still null

取消引用空指针,即未定义行为。你很幸运,它只是崩溃。

正确(但仍然不安全)的方法是这样的:

bool getClassData(ClassData* classData) {
  if (m_classData!=0 && classData!=0)
    { classData->a = m_classData->a; return true; }
  else return false;
}

我说“仍然不安全”,因为此函数无法真正验证这些指针指向有效的数据结构。为了避免这种危险,你必须避免使用如此多的指针,并查看引用。

答案 1 :(得分:0)

使用值而不是指针可以简化操作,还可以消除内存泄漏。见live example

#include <iostream>

class ClassData
{
public:
    ClassData() { a=-1; }

public:
    int a;
};

class MyClass
{
public:
    MyClass() {  }
    explicit
    MyClass(ClassData const& classData) { 
        m_classData = classData; 
        m_classData.a=1; 
    }

    ClassData const& getClassData() const {
        return m_classData;
    }

private:
    ClassData m_classData;
};

int main()
{
    ClassData classData;
    MyClass myClass( classData );

    classData = myClass.getClassData();
    int value = classData.a; 

    std::cout << value;
}