2015-07-10 33 views
0

我遇到了一个令我感到困惑的问题。这与我是选择存储对象还是指向它的指针有关。字符串在构造函数中被赋值,但之后变为空白C++

这是我的课:

class Test { 
public: 
    std::string abc; 
    int x; 

    Test(std::string def, int y) { 
     abc = def; 
     cout << abc << endl; //THIS ALWAYS GIVES "ghi" 
     x = y; 
    } 
}; 

把它作为一个指针:

Test* T1 = &Test{ "ghi", 100 }; 
    cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?** 
    cout << T1->x << endl; //THIS GIVES 100 

把它作为一个对象本身:

Test T2 = Test{ "ghi", 100 }; 
    cout << T2.abc << endl; //THIS GIVES "ghi" 
    cout << T2.x << endl; //THIS GIVES 100 

我是比较新的C++但基于我的理解,T1-> abc应该取消引用指针T1(因此我有一个Test对象),然后访问m对该Test对象的abc进行ember。由于我已经创建了该对象,因此应该是“ghi”。但是,这是空白的。

显然,这只适用于字符串成员,而不是整数成员,因为T1-> x正常工作。

当我存储对象而不是指向它的对象时,问题不存在,如对象T2所示。

我检查过在T1和T2施工期间,abc总是“ghi”里面的的构造函数。不知何故,建设后,字符串就消失了。

此外,根据我读到的,abc = def复制字符串内容而不是指针,所以它可能不是范围问题。

https://msdn.microsoft.com/en-us/library/b930c881.aspx非常清楚,在任何情况下,是否 - >或。被使用,可以进行分配。

搜索谷歌和stackoverflow没有帮助。因此你的赞赏。提前致谢。

class Test { 
public: 
    std::string abc; 
    int x; 

    Test(std::string def, int y) { 
     abc = def; 
     x = y; 
    } 
}; 

int main() { 

    Test* T1 = &Test{ "ghi", 100 }; 
    cout << T1->abc << endl; //THIS IS BLANK -- WHY!? 
    cout << T1->x << endl; //THIS GIVES 100 

    Test T2 = Test{ "ghi", 100 }; 
    cout << T2.abc << endl; //THIS GIVES "ghi" 
    cout << T2.x << endl; //THIS GIVES 100 

    return 0; 
} 
+5

'Test * T1 =&Test {“ghi”,100};'这是错误的。不要这样做。您将该指针重新设置为临时对象的地址(在该行的分号后不会存在)。 – Borgleader

+1

据我所知,g ++甚至不会让你编写这样的代码。 –

+0

在我的实际问题中,我有一个抽象基类,称之为测试。我也有一些派生类,但是我选择实例化的派生类只能在运行时确定。因此,我正在使用指向Test的指针来保存派生类的指针。因此我需要一个指针。有一个更好的方法吗? – emoPuppy

回答

2

此构造:

Test{ "ghi", 100 }; 

创建临时变量,您试图指向。这是错误的。

如果你想存储它使用指针:

Test* T1 = new Test{ "ghi", 100 }; 

cout << T1->abc << endl; //This is not blank anymore 
cout << T1->x << endl; 

delete T1; //Do NOT forget this! 

顺便说一句,如果你想知道,为什么这条线:

cout << T1->x << endl; 

仍在评估,以100:当对象被销毁,其所有成员也被销毁(在调用它们的析构函数方面)。由于xint,因此它在非操作中的析构函数和其占用的内存内容不会更改。

另一方面,abc是和std::string,它在销毁期间释放分配的内存 - 因此T1->abc指的是空字符串。

+0

谢谢(还有其他的)。对于问什么竟然是这样一个直截了当的问题抱有歉意。学习一种新语言当然不容易。我阅读了一些建议,我们应该避免使用新版本,因为非新版本在不再需要时会自动删除。所以我从这里得出的结论是,只有当对象本身被变量引用时,“自动”才会考虑它是否被指针引用。 – emoPuppy

1
Test* T1 = &Test{ "ghi", 100 }; 

请不要这样做。这正是导致你的问题。而是使用

Test* T1 = new Test("ghi", 100); 

因为第一种方式创建一个临时对象,你试着去打印字符串之前它消失的参考。

它适用于非指针,因为您将临时对象赋予新对象。

不记得删除(因为你已经使用了新)

delete T1; 

或者,如πάνταῥεῖ指出的那样,这将是更安全,更好的C++编码习惯,将使用smart pointer。想到的最相关的是unique_ptr。

std::unique_ptr<Test> T1(new Test()); 
std::cout << T1->abc << std::endl; 
... 
+0

请注意,您必须'删除T1;' – WorldSEnder

+0

@WorldSEnder不能忘记!讨厌的指针...:P –

+0

_“反而使用...”_不会导致相同的困境。 –

1
Test* T1 = &Test{ "ghi", 100 }; 

临时右值Test{ "ghi", 100 }立即超出范围,并停止该语句之后存在。

因此取消引用它像

cout << T1->abc << endl; 

只是调用一个悬摆指针Undefned行为

+0

括号内应该是括号吗?或者有什么我想念的? –

+0

@OlivierPoulin在当前标准中,可以使用这两种形式。 –

+0

有意思,谢谢! –

1

这段代码

Test* T1 = &Test{ "ghi", 100 }; 
cout << T1->abc << endl; //**THIS IS BLANK -- WHY!?** 
cout << T1->x << endl; //THIS GIVES 100 

是未定义的行为,因为语句后

Test* T1 = &Test{ "ghi", 100 }; 

临时对象测试{ “GHI”,100}将被删除,指针变为无效。

一个有效的代码可以看看下面的方式

Test* T1 = new Test{ "ghi", 100 }; 

cout << T1->abc << endl; 
cout << T1->x << endl; 

delete T1; 

或代替指针,你可以使用一个常量引用到临时对象。例如,

const Test &T1 = Test{ "ghi", 100 }; 

cout << T1.abc << endl; 
cout << T1.x << endl; 

临时对象将在活动时存在,而引用将存活。

相关问题