C ++公共构造函数地址

时间:2011-04-02 23:09:30

标签: c++ constructor

编写下面的代码后:

#include <iostream>

using namespace std;
typedef struct Node {
    int value;

    Node(int index) { 
        value = index;
    }
} Node;

int main() {
    Node* arr[10];
    for(int i = 0; i < 10; i++) {
        arr[i] = &Node(i);
    }
    for(int i = 0; i < 10; i++)
        cout << arr[i]->value << endl;
}

我看到代码只打印了9个而不是0到9之间的所有数字。 在调试代码之后,我看到每个i的arr [i]的地址是相同的,并且Node(i)只为arr [i]释放了一次空间,之后唯一的是它value = index没有释放任何其他空间。为什么呢?

3 个答案:

答案 0 :(得分:6)

这一行:arr[i] = &Node(i);正在存储指向临时对象的指针。 Node(i)创建一个临时对象,可以在语句结束时对其进行破坏,此时对它的所有引用都将变为无效,这意味着解除引用arr[i]的任何代码的结果都将是未定义的。在这种情况下你得到所有9的原因是因为编译器正在优化代码 - 因为一次只创建了1个临时Node(i),编译器只是每次循环时重用该内存。

要解决此问题,请为堆中的每个对象分配内存:arr[i] = new Node(i);。然后,当您完成使用它们时,您还需要记住删除每一个:

for (int i=0; i < 10; ++i) {
    delete arr[i];
}

如果您想进一步调查,请尝试在Node类中添加一些代码以查看正在发生的事情:例如,在构造函数中打印出this的地址,和/或创建一个析构函数只是打印一条消息,这样你就可以看到它被调用了。

答案 1 :(得分:5)

要创建新对象,请使用new Node(i),否则您将在堆栈上创建临时对象,这就是它们完全相同的原因。

请记住在从新回来的每个对象上调用delete。

答案 2 :(得分:3)

&Node(i)

此表达式创建临时变量并返回其地址。然后销毁临时表,并在下次计算表达式时,在同一个地方创建另一个临时表 - 因此地址相同。

您应该可以消除指针的使用,并为Node引入默认值。

#include <iostream>

using namespace std;
typedef struct Node {
    int value;

    Node(int index) { 
        value = index;
    }

    Node() : value( 0 ) {} // allow default construction
} Node;

int main() {
    Node arr[10]; // default-construct array values
    for(int i = 0; i < 10; i++) {
        arr[i] = Node(i);
    }
    for(int i = 0; i < 10; i++)
        cout << arr[i].value << endl;
}

不要单独为每个对象使用new Node始终使用容器对象来管理具有类似语义的一组对象。您可以在此处使用std::vector,如果您拥有std::array,则可以使用std::vectornew引入的开销将小于{{1}}引入的开销。