0

我目前正在学习如何使用 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,因为它没有将 new 和 delete 声明分开,并且使我在完成后不太容易忘记删除对象。但它是一个返回类型 void 并且我发现代码的可读性较差,因为我必须实际检查函数的作用(通常这意味着读取其他文件)。

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

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

谢谢你的建议!

4

4 回答 4

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 方法可能会被跳过,因为您使用的结构只有公共成员变量。

于 2013-07-23T12:03:31.303 回答
3

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

于 2013-07-23T12:03:41.253 回答
2

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

更好的(imo)方法如下所示:

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){}

在这种情况下,您的属性在构造函数主体之前初始化(请参阅 c++ 构造函数循环)。

于 2013-07-23T12:10:42.237 回答
1

既然你正在学习 C++,我建议你学习 C++11。在这种情况下,您应该真正考虑智能指针(例如 std::unique_ptr),或者可能更多地考虑在堆栈上创建项目并让编译器处理自动销毁 - RAII(资源获取是初始化)原则。

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

创建对象的函数通常是工厂,因此稍后您可能希望将 boost:value_factory<> 视为一种更简洁的方式来执行此操作。

于 2013-07-23T12:07:51.663 回答