C++ cli C++/CLI,“;常数;对跟踪句柄的引用
我在代码中发现了如下内容:C++ cli C++/CLI,“;常数;对跟踪句柄的引用,c++-cli,C++ Cli,我在代码中发现了如下内容: void foo(IList<int>^ const & list ) { ... } void foo(IList^const&list){…} 这个^const&是什么意思?我查看了C++/CLI规范,但没有找到关于持续跟踪引用的注释,也没有找到^&组合 这合法吗?它是跟踪句柄的常量引用 它允许您通过引用而不是通过值传递句柄。大概作者认为它比复制句柄更有效 如果作者想使手柄保持恒定,他应该使用以下两种方法之一 Method(TestClas
void foo(IList<int>^ const & list ) { ... }
void foo(IList^const&list){…}
这个^const&
是什么意思?我查看了C++/CLI规范,但没有找到关于持续跟踪引用的注释,也没有找到^&
组合
这合法吗?它是跟踪句柄的常量引用 它允许您通过引用而不是通过值传递句柄。大概作者认为它比复制句柄更有效 如果作者想使手柄保持恒定,他应该使用以下两种方法之一
Method(TestClass const ^ const & parameter)
Method(TestClass const^ parameter)
或者
方法(TestClass const^¶meter)
-但是调用方必须首先const起句柄
具有
TestClass常量^constHandle=nonstHandle
每种方法的示例如下:
// test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
ref class TestClass
{
public:
void setA(int value)
{
a = value;
}
TestClass() :
a(10)
{
}
private:
int a;
};
class TakesHandle
{
public:
void methodX1(TestClass const ^ const & parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX2(TestClass const^ parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX3(TestClass const^& parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TakesHandle takes;
TestClass ^ test1 = gcnew TestClass();
// compiles
takes.methodX1(test1);
// compiles
takes.methodX2(test1);
TestClass const ^ constHandle = test1;
takes.methodX3(constHandle);
return 0;
}
<>这个代码可能是由C++程序员编写的,使用普通的C++习语编写C++/CLI。这是完全错误的,只有当句柄存储在堆栈上时,才可能将引用传递给跟踪句柄。如果传递的列表引用存储在堆上对象的字段中,它将无法工作,垃圾收集器可能会移动它并使指针无效。编译器将捕获它并生成一个错误。^已经是引用,不需要其他引用 如果没有引用,const关键字也就没有什么意义了。CLR以前从未这样做过,但它无法强制执行。这并不重要,这段代码不能从任何其他.NET语言调用。它们不会生成指向跟踪句柄的指针 只要修复它,保留这样的坏代码没有什么意义:
void foo(IList<int>^ list ) { ... }
void foo(IList^list){…}
显示引用无法工作的代码示例:
using namespace System;
using namespace System::Collections::Generic;
ref class Test {
public:
IList<int>^ lst;
void foo(IList<int> const &list) {}
void wontcompile() {
foo(lst); // C3699
IList<int>^ okay;
foo(okay);
}
};
使用名称空间系统;
使用命名空间System::Collections::Generic;
参考等级测试{
公众:
IList^lst;
void foo(IList const&list){}
void wontcompile(){
foo(lst);/C3699
好吧;
傅(好);
}
};
这与常量IList^&
相同吗?那么这种构造与仅仅通过值传递跟踪指针(IList^
)有什么区别呢?@liori no.2-如果你像在评论中那样传递跟踪指针,它就不会得到常量。我的错误@Vulcan Eager。不一样,我得出了相似的结论。问题是,该函数位于建议我使用的外部库中。我设法在自己的代码中重新实现了它。谢谢你证实我的担心,你说得有一部分是对的。您完全可以将句柄的引用传递给托管堆。问题是不能在ref类型上使用const方法,因此c++/cli不允许您执行正确的const。运行时不会自动将某些内容强制转换为const,但如果将参数标记为const,则会与调用者形成一个协定,表示不会更改其对象。不,引用存储在哪里很重要。“Const”编码在程序集元数据的属性中,其他语言将忽略它们。@Ben,你说的“Const correct attributes”是什么意思,为什么modopt(IsConst)
不是吗?几乎任何其他语言都不尊重它,这是另一回事…@Pavel,我的意思是C++/CLI允许您创建const控件^
,但这样做没有用,因为即使是只读操作也不允许通过const句柄。e、 g.myArray->size()
在const std::vector*
上运行良好,但无法读取ArrayList的Length
属性。除了const成员函数之外,您甚至无法将两个const System::Object^
传递给ReferenceEquals
,因为BCL类中完全缺少正确使用const所需的属性。看起来函数希望通过引用接受其句柄,使句柄的更改在函数中可见。但是语法是可疑的,对于托管代码中的引用,您需要跟踪引用。请尝试void foo(IList^%list)
@Ben-您肯定需要对托管堆上的对象进行跟踪引用,但是c++/cli中的堆栈语义允许您通过本机引用传递句柄,因为句柄可以保护您不被重定位。据我所知,一旦编译本机引用IList^%
是对变量的引用,其中变量的类型为IList^
,本机引用将最终成为跟踪引用。如果该变量存储在ref类
中,则它可能会被垃圾收集器移动,因此使用本机引用(IList^&
)将失败。变量的类型没有任何区别,只是变量的位置不同。值得一提的是,一些marshall\u as
专门化了marshall\u cppstd.h
takeSystem::String^const&
参数。这很烦人,因为如果我想将String^
字段封送到std::String
,我必须首先将其复制到堆栈中。