用C ++创建对象的函数

时间:2013-07-23 11:59:17

标签: c++ function oop object pointers

我目前正在学习如何使用C ++中的函数来操作对象,到目前为止,我已经到了以下几点:

如果您的对象可能很大,请不要将其作为局部变量,即将其保留在堆中以节省复制时间。

具体来说,我感兴趣的是我们正在使用一个创建以前不存在的对象的函数的场景。 我已经将以下小例子放在一起,以展示如果你有一个函数该怎么做:

#include <iostream>
using namespace std;

struct obj {
    int first;
    int second;
};


void setFirstVersionA(int a, obj * s)
{
    s->first = a;
}

obj * setFirstVersionB(int a)
{
    //in Version B I am creating a new object in the function but have to run delete outside
    obj * s = new obj();
    s->first = a;
    return s;
}


int main(int argc, const char** argv)
{
    obj * myobj = new obj();
    setFirstVersionA(2,myobj);
    //now I have the new obj in *i
    cout << myobj->first;
    delete myobj;

    //this is an alternative to passing a pointer directly:

    //no need to re-declare the pointer as delete only erases the myobj data
    myobj = setFirstVersionB(3);
    //now I have the new obj in *i
    cout << myobj->first;
    delete myobj;

    return 0;
}

据我所知,这两个函数都能达到相同的效果。

我更喜欢版本A,因为它不会分隔新声明和删除声明,并且一旦完成,我就不会忘记删除对象。但它是一个返回类型的void,我发现代码的可读性较差,因为我必须实际检查函数的作用(通常它意味着读取其他文件)。

我更喜欢B版,因为它返回了我想要改变的“东西”。所以我立即知道,这个函数改变了那个人(在这种情况下是obj)。但它分开,新的和删除。老实说,我发现在我的代码中有一系列void函数并没有立即看到它们的作用。 此外,这里已经写了很多关于不返回指向局部变量的指针,但在变体B中,虽然对象是在函数内创建的,但它不是局部变量(因为它位于堆中)。正确?

有更好的方法吗? 此外,“创建之前不存在的对象的函数”听起来很像构造函数。 :)我应该为每个对象创建一个带有构造函数的类吗?

感谢您的建议!

4 个答案:

答案 0 :(得分:3)

正确的方法可能是创建一个以值为参数的构造函数:

struct obj
{
    obj(int f) : first(f) {}
    // ...
};

// ...

obj myobj(2);

或者有一个setter函数:

struct obj
{
    void set_first(int f) { first = f; }
    // ...
};

// ...

obj myobj;
myobj.set_first(2);

上述方法当然可以合并,所以你们都有一个专门的构造函数和一个setter方法。

虽然可以跳过setter方法,因为您使用的结构只包含公共成员变量。

答案 1 :(得分:3)

您应该忽略您找到的建议,在堆栈上分配对象,并按值返回。 C ++,尤其是C ++ 11,具有特定的优化功能,可以提高效率:复制省略(各种情况允许编译器就好像两个对象实际上就是一个)并移动语义(C ++ 11中新增了,允许编译器识别不再需要旧对象并做一些比复制更有效的事情。

答案 2 :(得分:2)

我想你来自Java世界(obj * myobj = new obj();语法) 它在C ++中是正确的,但是在不必要时你不应该使用指针。

更好的(imo)approch看起来像:

int main(int argc, const char** argv){
    Obj myObject; // your object now exists, fully usable.
    myObject.setValue(42); //classic, java-like setter

    Obj mySecondObect(42); //even better when you know the value at construct time.
}

Obj的ctr看起来像:

Obj::Obj(int myValue) : _myVal(myvalue){}

在这种情况下,你的attribut在构造函数体之前被初始化(参见c ++构造函数循环)。

答案 3 :(得分:1)

由于你正在学习C ++,我建议学习c ++ 11。在这种情况下,您应该考虑智能指针(例如std :: unique_ptr),或者更多关于在堆栈上创建项目并让编译器负责自动销毁 - RAII(Resouce aquisition is initialisation)原则。

这样你就可以避免新的/删除潜在的内存泄漏,并创建更可靠的代码。

创建对象的函数通常是工厂,因此稍后您可能需要查看boost:value_factory&lt;&gt;作为一种更干净的方式。