Export (0) Print
Expand All

System::String Handling in Visual C++

Updated: October 2009

This topic discusses how the Visual C++ compiler processes string literals when you run it by using the /clr compiler option. To use /clr, you must also use the common language runtime (CLR), C++/CLI syntax and managed objects. For more information about /clr, see /clr (Common Language Runtime Compilation).

When you use /clr, the compiler converts string literals to strings of type String. However, to preserve backward compatibility with existing code, there are these exceptions:

  • Exception handling. When a string literal is thrown, the compiler catches it as a string literal.

  • Template deduction. When a string literal is passed as a template argument, the compiler does not convert it to a String. String literals passed as a generic argument are promoted to String.

The compiler also has built-in support for the following operators, which you can override to customize their behavior:

  • System::String ^ operator +( System::String, System::String);

  • System::String ^ operator +( System::Object, System::String);

  • System::String ^ operator +( System::String, System::Object);

When passed a String, the compiler will box, if necessary, and then concatenate the object (with ToString) with the string.

When you compile by using /clr:oldSyntax, string literals are not converted to String.

NoteNote:

The caret ("^") indicates that the declared variable is a handle to a C++/CLI managed object.

For more information see C++ String Literals.

// string_operators.cpp
// compile by using: /clr
// In the following code, the caret ("^") indicates that the 
// declared variable is a handle to a C++/CLI managed object.
using namespace System;

int main() {
   String ^ a = gcnew String("abc");
   String ^ b = "def";   // same as gcnew form
   Object ^ c = gcnew String("ghi");

   char d[100] = "abc";

   // variables of System::String that return a System::String
   Console::WriteLine(a + b);
   Console::WriteLine(a + c);
   Console::WriteLine(c + a);

   // accessing a character in the string
   Console::WriteLine(a[2]);

   // concatenation of three System::Strings
   Console::WriteLine(a + b + c);

   // concatenation of a System::String and string literal
   Console::WriteLine(a + "zzz");

   // you can append to a System::String ^
   Console::WriteLine(a + 1);
   Console::WriteLine(a + 'a');
   Console::WriteLine(a + 3.1);

   // test System::String ^ for equality
   a += b;
   Console::WriteLine(a);
   a = b;
   if (a == b)
      Console::WriteLine("a and b are equal");

   a = "abc";
   if (a != b)
      Console::WriteLine("a and b are not equal");

   // System:String ^ and tracking reference
   String^% rstr1 = a;
   Console::WriteLine(rstr1);

   // testing an empty System::String ^
   String ^ n;
   if (n == nullptr)
      Console::WriteLine("n is empty");
}
abcdef abcghi ghiabc c abcdefghi abczzz abc1 abc97 abc3.1 abcdef a and b are equal a and b are not equal abc n is empty

The following sample shows that you can overload the compiler-provided operators, and that the compiler will find a function overload based on the String type.

// string_operators_2.cpp
// compile by using: /clr
using namespace System;

// a string^ overload will be favored when calling with a String
void Test_Overload(const char * a) { 
   Console::WriteLine("const char * a"); 
}
void Test_Overload(String ^ a) { 
   Console::WriteLine("String ^ a"); 
}

// overload will be called instead of compiler defined operator
String ^ operator +(String ^ a, String ^ b) {
   return ("overloaded +(String ^ a, String ^ b)");
}

// overload will be called instead of compiler defined operator
String ^ operator +(Object ^ a, String ^ b) {
   return ("overloaded +(Object ^ a, String ^ b)");
}

// overload will be called instead of compiler defined operator
String ^ operator +(String ^ a, Object ^ b) {
   return ("overloaded +(String ^ a, Object ^ b)");
}

int main() {
   String ^ a = gcnew String("abc");
   String ^ b = "def";   // same as gcnew form
   Object ^ c = gcnew String("ghi");

   char d[100] = "abc";

   Console::WriteLine(a + b);
   Console::WriteLine(a + c);
   Console::WriteLine(c + a);

   Test_Overload("hello");
   Test_Overload(d);
}
overloaded +(String ^ a, String ^ b) overloaded +(String ^ a, Object ^ b) overloaded +(Object ^ a, String ^ b) String ^ a const char * a

The following sample shows that the compiler distinguishes between native strings and String strings.

// string_operators_3.cpp
// compile by using: /clr
using namespace System;
int func() {
   throw "simple string";   // const char *
};

int func2() {
   throw "string" + "string";   // returns System::String
};

template<typename T>
void func3(T t) {
   Console::WriteLine(T::typeid);
}

int main() {
   try {
      func();
   }
   catch(char * e) {
      Console::WriteLine("char *");
   }

   try {
      func2();
   }
   catch(String^ str) {
      Console::WriteLine("String^ str");
   }

   func3("string");   // const char *
   func3("string" + "string");   // returns System::String
}
char * String^ str System.SByte* System.String

Compiler option: /clr

Date

History

Reason

October 2009

Added context to associate C++/CLI syntax with the /clr compiler switch.

Customer feedback.

Community Additions

ADD
Show:
© 2014 Microsoft