1

In below code example, memory for an integer is dynamically allocated and the value is copied to the new memory location.

main() {
    int* c;
    int name = 809;
    c = new int(name);
    cout<<*c;
}

But, when I try to do the same with a char string it doesn't work. Why is this?

int main() {
    char* p;
    char name[] = "HelloWorld";
    p = new char(name);
    cout << p;
}
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
Ravi Raaja
  • 19
  • 1
  • 4
  • This is almost C. Try `std::string` or `std::vector` (if you want a buffer, not string). – Incomputable May 29 '17 at 10:57
  • c=new int(name) and c=new char(name) are not both identical, the way i'm saying that they are not identical is that for integer you are providing an integer value, but for character you are giving array of character, that way they are not identical, you could try it with the array of integer, here in integer case it's allocating only enough memory for one integer. – Ratul Sharker May 29 '17 at 10:59
  • C-style arrays use different syntax than every other object for historical reasons. You would do well to avoid them; use C++ style arrays and strings – M.M May 29 '17 at 11:07
  • 1
    Use [std::string](http://en.cppreference.com/w/cpp/string/basic_string) – Basile Starynkevitch May 29 '17 at 11:12

4 Answers4

3

Your second example doesn't work, because char arrays work differently than integer variables. While single variables can be constructed this way, this doesn't work with (raw) arrays of variables. (As you have observed.)

In C++ you should try to avoid handling pointers and raw arrays as much as you can. Instead, you'd rather use the standard library containers to take a copy of that string to an array of dynamically allocated memory. std::string and std::vector<char> are especially suitable in this case. (Which one should be preferred depends a bit on the semantics, but probably it's the std::string.)

Here's an example:

#include <string>
#include <vector>
#include <cstring>
#include <iostream>

int main(){
    char name[] = "Hello World";

    // copy to a std::string
    std::string s(name);
    std::cout << s << '\n';

    // copy to a std::vector<char>
    // using strlen(name)+1 instead of sizeof(name) because of array decay
    // which doesn't occur here, but might be relevant in real world code
    // for further reading: https://stackoverflow.com/q/1461432
    // note that strlen complexity is linear in the length of the string while
    // sizeof is constant (determined at compile time)
    std::vector<char> v(name, name+strlen(name)+1);
    std::cout << &v[0] << '\n';
}

The output is:

$ g++ test.cc && ./a.out
Hello World
Hello World

For reference:

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • `std::string s(name);` seems simpler – M.M May 29 '17 at 11:12
  • Thanks for spotting! Adapted that bit. – moooeeeep May 29 '17 at 11:14
  • 2
    `std::cout << &v[0] << '\n'` is UB, because the vector is not null-terminated. – zett42 May 29 '17 at 11:23
  • @zett42 Absolutely! I changed the construction to now include the null-terminator from the original buffer. And it makes me think if the added value of that part in demonstrating the use of a vector as a char buffer still justifies the added complexity. – moooeeeep May 29 '17 at 11:29
  • 1
    Since `name` is an array and not a pointer, that null-including vector could be made without the extra pass by strlen: `std::vector v{std::begin(name), std::end(name)};`. Or with std::size/sizeof/etc – Cubbi May 29 '17 at 13:03
  • @Cubbi Yes that would work here, as the array did not decay to a pointer in this example. I thought I'd give a general example to avoid confusion when it is later used in a context with decay. – moooeeeep May 29 '17 at 14:36
1

Your second code snippet does not work because new int(name) initializes an int from an int, while new char(name) tries to initialize a char from a char[11] array.

There is no array constructor taking an array in C++. In order to make a copy of an array, you must allocate an array, and then copy data into it:

p = new char[sizeof(name)];
std::memcpy(p, name, sizeof(name));
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

In the first case you allocate memory for a single int object, and initialize with a single int value. Great, this works.

In the second case you allocate memory for a single char object, and initialize it with an array of characters. It does not work, an array of objects does not fit in a memory of a single object. Besides, the array has a different type, so the initialization is ill-formed.

To allocate memory for an array of characters (such as a string), you can use new[]:

char* ptr = new char[11]{"HelloWorld"};

PS. The GNU compiler (until the current version 7 at least) and clang (until version 4) have a bug which breaks the above initialization. A workaround is to copy the string after allocation.

PPS. While it is useful to learn these things, don't do manual memory management in actual programs. Use RAII containers such as std::string for strings and std::unique_ptr for single dynamic objects.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

Your code doesn't work as you are trying to initialize a char instead of array of characters. In order to dynamically allocate memory, you need to allocate the memory and then copy over the content.

p = new char[strlen(name) +1];
std::strcpy(p, name);
nevihs
  • 991
  • 1
  • 12
  • 23