确认基本的c ++语法

时间:2012-06-16 00:17:40

标签: c++ reference

我是一名转向C ++的java程序员。我有一个类中的数据列表。我想返回存储在类变量中的列表的内容,然后生成一个新列表并将其存储在类变量中,这样我就可以开始将新数据添加到空列表中。我想我知道怎么做,但我想仔细检查,因为我是新手参考和c ++内存管理,不希望以后出现愚蠢的内存泄漏。 (注意,我不能轻易复制我的实际代码所以我只是重写它,如果我输入错误,请原谅我。)

我相信正确的语法是这样的:

//mylist is typedef of a list type
mylist& temporaryList=classList;
classList=myList();
return classList;

这种语法是否正确?另外,我是否必须担心在任何时候释放返回的变量或classList变量,或者RIAA会为我处理这一切吗?

很抱歉提出这么简单的问题,但感谢您确认我的假设。

3 个答案:

答案 0 :(得分:2)

mylist& temporaryList=classList;

tempraryList是一个参考。当您更改classList时,它也会发生变化。试试这个:

mylist tempraryList = classList;

这将复制mylist的复制构造函数,创建一个新的复制构造函数,而不是仅混淆另一个。


return classList;

这将返回您刚刚决定应该是新列表的那个。您想要返回temporaryList。但是,请确保它不是通过引用返回的,因为temporaryList将超出范围(清理自身,因为它已在堆栈中分配),并且您最终会得到一个悬空引用。

同样,通常,类不是分配默认构造函数的结果,而是可以提供一种reset函数来做到这一点,而不会产生另一个对象的开销。

答案 1 :(得分:1)

正如@chris指出你有一个问题,你使用的是引用,引用具有很好的功能,它们别名实际对象几乎没有成本,但在你的情况下它意味着当您重置成员列表时,您将重置程序中的 only 列表。

正如@chris所指出的那样,对代码的简单朴素修复就是复制列表,然后重置原始文件:

mylist getAndClear() {
   mylist temporaryList=classList;    // make a copy
   classList=myList();                // reset the internal
   return temporaryList;              // return the **copy**
}

现在,这种方法的问题在于,当您知道原始列表将立即被销毁时,您将承担复制成本。您可以使用复制和交换习语(*)来避免这种成本:

mylist getAndClear(){       mylist tmp; //空       swap(tmp,classList); //交换内容,现在classList为空                                           // tmp保存数据       返回tmp;    }

这假设myliststd::list。如果不是,请确保实现swap(或在C ++ 11中移动构造函数,这将启用高效的std::swap)。


(*)虽然这似乎不是 copy-and-swap 习惯用法的直接应用,但实际上,要应用的修改是清除列表。执行复制并对副本应用更改(在这种情况下,避免复制,因为更改将其清空),然后在操作成功完成后交换内容。

答案 2 :(得分:0)

chris提到使用成员函数重置或清除对象,如下所示:

mylist tmp = classList;
classList.clear();
return tmp;

但是你通常可以通过首先避免副本来做得更好。

mylist tmp;
std::swap(tmp,classList);
return tmp;
  

另外,我是否需要担心随时释放返回的变量或classList变量,或者RIAA会为我处理这一切吗?

除非您delete某个地方,否则您不需要new资源。如果您使用new,那么您还应该使用智能指针,这样您仍然不需要delete任何内容。

要理解来自Java的C ++最重要的事情之一就是C ++对象默认是类似于值的对象。那就是:

class A {
    bool bar_called;
public:
    A() : bar_called(false) {}
    void bar() { bar_called = true; }
    bool has_bar_been_called_on_this_object() { return bar_called; }
};

void foo(A a) {
    a.bar();
}

int main() {
    A a;
    foo(a);
    std::cout << a.has_bar_been_called_on_this_object() << '\n';
}

输出将指示在a上未调用。 Java使用,但试图隐藏指针。所以一旦你弄清楚C ++中的指针,事情应该对你更有意义,然后你就能弄明白如何使用指针。

Object o = new Object(); // Java hides the fact that o is a pointer to an Object, but fails to hide the consequences
Object b = o; // b is a pointer to an object, the same Object o points to.

// Equivalent C++
Object *o = new Object();
Object *b = o;

从您提供的C ++代码来看,在Java中,您可以做出类似这样的事情:

mylist tmp = classList;
classList = new mylist();
return tmp;

C ++中的等价物是:

mylist *tmp = classList; // classList is a pointer to a new'd up list.
classList = new mylist();
return tmp;

然而,这不是自然的C ++。在C ++中,您通常不想使用指针,如果您想使用智能指针

std::shared_ptr<mylist> tmp = classList; // classList is a std::shared_ptr<mylist>
classList = std::make_shared<mylist>();
return tmp;

std::unique_ptr<mylist> tmp = std::move(classList); // classList is a unique_ptr
classList = std::unique_ptr<mylist>(new mylist()); // careful here, don't go calling a bunch of functions inside the mylist initializer, it's dangerous for reason beyond the scope of this post
return tmp;

但是C ++的方法实际上是完全避免使用指针。

mylist tmp; // classList is not a pointer at all
std::swap(tmp,classList); // the values of classList and tmp are swapped
return tmp; // tmp is returned by value, tmp has the same value as classList, but is not the same object, tmp and classList are objects, not pointers to objects as they are in Java or in the above C++ examples.