C++/CLI 传递字符串 ^ 作为跟踪引用无法按预期工作



我在VS 2010中使用C++/CLI。多亏了这个答案,我了解到在 C++/CLI 中,您通过引用传递一个对象,如下所示

voin func(String ^ %string){
//modify string
}

我想做的是将一些参数传递给GetInput形式的构造函数。然后修改它们从用户输入到此窗体。当窗体关闭时,调用方窗体将获取在GetInput窗体中输入的值。

它对我有用List<double>,但不适用于String^.这是代码:

public ref class GetInput : public System::Windows::Forms::Form
{
public:
    List<double>^ _data;
    String ^ _string_data;
    GetInput(List<double>^ %data, String ^ %string_data){
        _data = data;
        _string_data = string_data;
        //this code is here just for the sake of an example, 
        //it's actually in one of the methods
        _data->Add(0.5); 
        _string_data = "15";
    }
    //void buttonClickHandler where i actually want to modify data and string_data
}

List _data和传递的data都被修改了,但是当我修改String _string_data时,原始string_data保持不变。但是,如果我修改string_data本身 - 它可以正常工作。此外,跟踪引用不能是类的成员,因此将_string_data声明为引用不起作用。

显而易见的解决方法是通过由一个String^组成的List^,但我想知道为什么它不起作用,以及是否有办法让我的方法起作用。来自本机C++,这似乎是一种非常简单的方法 - 只需将指针传递给数据即可。但是C++/ClI跟踪参考是不同的。

我还读到"当对象在垃圾收集堆上移动时,跟踪引用会更新。(来源(。有人可以澄清这意味着什么吗?我怀疑这包含我问题的答案,但我不太明白:(

更新:基本上我想在 C++/CLI 中执行此操作:

class GetInput {
    string * s; 
    GetInput(string * caller_wants_this_modified){ 
        s = caller_wants_this_modified; 
    } 
    void method_to_modify_the_string(){ 
        (*s) = "New string value"; // modifies the string passed by the caller 
    } 
}

我需要将传递给构造函数的指针保存为类成员,然后在其中一个成员函数中更改此指针指向的数据。

但是C++/ClI跟踪参考是不同的

认为"跟踪参考"有一些神奇的东西,也许是让你在这里陷入麻烦的原因。 C++/CLI 语言和文档对此进行了繁重的处理,它是为本机C++程序员编写的。 实际上,这一切并没有那么不同。

这只是一个指针。

它的行为也与指针完全相同,无论是在处理器上的物理上还是在语法上。 它唯一"特别"的是垃圾收集器可以找回它。 有必要,以便它可以完成其工作。 C++/CLI 设计人员选择使用 ^ 而不是 *,因为它们确实有限制。 普通的,例如,您不能使它成为非托管类的成员。 GC 无法知道它在内存中的位置,因此无法完成其工作。

你的问题很简单,你有两个指针。 _string_datastring_data . 请注意,您选择的名称并不能完全帮助您正确使用。 您更新了_string_data指针,在分配之后,它现在指向"15"。 但不是你通过引用传递的指针,它仍然指向原始字符串。 因此,当然不会将任何更改传播回调用方。 不知道意图是什么,但任意:

  _string_data = "15";
  string_data = _string_data;

现在,调用方还将看到其引用更新为"15"。 两个指针现在都指向同一个对象。

请注意,您在List<>论点上也弄错了。 您没有更新data指针。 您也不需要,您没有创建新的 List 对象。 代码仅修改了对象,而不修改指向对象的指针。 因此,通过引用传递它是完全没有必要的。


还有一个细节与这个问题有关。 请注意,您通过调用其 Add(( 方法修改了 List<> 对象。 但是你不能对字符串做同样的事情。 它是不可变的,它的任何方法和属性都不允许您修改其内容。 这给了它非常理想的行为,字符串始终是线程安全的,并且作为参数传递给方法总是安全的。 确保它永远不能被修改。 它的行为类似于一个值。

或者换句话说,您必须通过引用传递字符串指针才能将更改传播回调用方。

请注意,List<> 不是不可变的,您的 Add(( 调用改变了对象。 使用您的类的客户端程序员不太可能期望发生这种情况。 C++ 中的 const 关键字是表达差异的好方法。 然而,它在 C++/CLI 中不能很好地工作,其他 .NET 语言不知道它。 您可以在声明中使用 const,它不能在运行时强制执行。

最新更新