C++ 将托管指针分配给带和不带地址运算符“%”的对象
C++ assigning managed pointers to an object with and without the address operator "%"
我是 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
编辑的对象 return 的引用,这对我来说是自始至终。但是在 dt = DateTime::Now
中发生了什么,因为如果 DateTime::Now
做 return 一个对象那么它不应该给我一个 cannot convert DateTime
to DateTime^
错误吗?似乎为了让第二个工作,DateTime::Now
需要 return DateTime::Now
创建的 DateTime
对象的引用,在这种情况下不应该是第一个一个 dt = %DateTime::Now
给出类似的错误 cannot convert DateTime^^
to DateTime^
or do do smart pointers work differently than normal pointers?
sets the dt pointer to the reference of the object returned by DateTime::Now
那是你出错的地方,DateTime::Now 不是 return 对象。它return是一个值,DateTime是一个值类型。引用类型和值类型之间的区别在 C++ 中完全不存在,但在 .NET 中却非常重要。你必须了解它才能编写出高效的代码,这非常不高效。
DateTime^ dt;
那是火车跳出轨道的地方,因为 DateTime 是一个值类型,所以你应该声明这个变量 不带 ^ 帽子。遗憾的是,C++/CLI 编译器允许这种语法并实际实现它。该变量存储值的 boxed 副本。故意装箱值是您始终要避免的事情,装箱转换并不便宜。具有值类型的 .NET 的全部意义在于使程序更快。
但是,是的,正如您发现的那样,C++/CLI 编译器知道如何装箱值而无需您明确说明。虽然应该避免,但有时值被装箱并不罕见。例如,无法调用虚拟 ToString() 方法。所以你不必使用 %
。装箱创造了所有值类型都派生自 System::Object.
的错觉
if(!dt)
我必须假设这就是您真正想要的,检测到一个变量是 "not initialized"。在那个 .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);
我是 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
编辑的对象 return 的引用,这对我来说是自始至终。但是在 dt = DateTime::Now
中发生了什么,因为如果 DateTime::Now
做 return 一个对象那么它不应该给我一个 cannot convert DateTime
to DateTime^
错误吗?似乎为了让第二个工作,DateTime::Now
需要 return DateTime::Now
创建的 DateTime
对象的引用,在这种情况下不应该是第一个一个 dt = %DateTime::Now
给出类似的错误 cannot convert DateTime^^
to DateTime^
or do do smart pointers work differently than normal pointers?
sets the dt pointer to the reference of the object returned by DateTime::Now
那是你出错的地方,DateTime::Now 不是 return 对象。它return是一个值,DateTime是一个值类型。引用类型和值类型之间的区别在 C++ 中完全不存在,但在 .NET 中却非常重要。你必须了解它才能编写出高效的代码,这非常不高效。
DateTime^ dt;
那是火车跳出轨道的地方,因为 DateTime 是一个值类型,所以你应该声明这个变量 不带 ^ 帽子。遗憾的是,C++/CLI 编译器允许这种语法并实际实现它。该变量存储值的 boxed 副本。故意装箱值是您始终要避免的事情,装箱转换并不便宜。具有值类型的 .NET 的全部意义在于使程序更快。
但是,是的,正如您发现的那样,C++/CLI 编译器知道如何装箱值而无需您明确说明。虽然应该避免,但有时值被装箱并不罕见。例如,无法调用虚拟 ToString() 方法。所以你不必使用 %
。装箱创造了所有值类型都派生自 System::Object.
if(!dt)
我必须假设这就是您真正想要的,检测到一个变量是 "not initialized"。在那个 .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);