我对c++比较陌生,正在学习如何使用指针,但是我遇到了一些让我对它们赋值感到困惑的事情。我有类似下面的代码:
DateTime^ dt;
...
while(true)
{
if(!dt)
{
//both of these work - compile and the loop will break after a minute
//dt = DateTime::Now;
dt = %DateTime::Now;
}
else if ((DateTime::Now - *dt).TotalMilliseconds > 60000)
{
break;
}
}
为什么这两种方法都有效?根据我的理解,dt = %DateTime::Now
将dt
指针设置为DateTime::Now
返回的对象的引用,这对我来说是无效的。但是在dt = DateTime::Now
中发生了什么,因为如果DateTime::Now
确实返回一个对象,那么它不应该给我一个不能转换DateTime
到DateTime^
的错误吗?似乎为了第二个工作,DateTime::Now
需要返回DateTime::Now
创建的DateTime
对象的引用,在这种情况下,第一个dt = %DateTime::Now
不应该给出类似的错误,不能将DateTime^^
转换为DateTime^
,或者智能指针的工作方式与普通指针不同?
将dt指针指向DateTime::Now
返回的对象的引用。
这就是你出错的地方,DateTime::现在不返回对象。它返回一个值, DateTime是一个值类型。引用类型和值类型之间的区别在c++中是完全不存在的,但在。net中是一个非常重要的问题。你必须理解它才能写出高效的代码,这非常不是高效。
DateTime ^ dt;
这就是火车脱轨的地方,因为DateTime是一个值类型,你应该声明这个变量而不带 ^帽。遗憾的是,c++/CLI编译器允许这种语法并实际实现了它。该变量存储值的盒装副本。有意地对值进行装箱是您总是希望避免的事情,装箱转换并不便宜。而。net拥有值类型的全部意义在于使程序更快。
但是,是的,正如您发现的那样,c++/CLI编译器知道如何将值框起来,而不必明确说明它。虽然应该避免,但有时值被框起来并不罕见。例如,不能调用虚拟ToString()方法。所以你不必使用%
。装箱创造了一种假象,即所有的值类型都派生自System::Object。
如果(dt)
我必须假设这就是你真正想要的,检测变量"未初始化"。在。net中有一个更有效的模式,你可以使用Nullable<>类型。这样的:
Nullable<DateTime> dt;
while (true) {
if (!dt.HasValue) {
dt = DateTime::Now;
}
else if ((DateTime::Now - dt.Value).TotalMilliseconds > 60000) {
break;
}
}
可以通过许多方式进行改进,您可以使用:
来避免半途而废的版本System::Threading::Thread::Sleep(60000);