如何在 unique_ptr 中使用 memcpy

how to use memcpy with unique_ptr

当我遇到这个时,我正在尝试学习智能指针。

{ //Example 1
    //String to be copied
    std::string strHello = "HelloWorld1";
    int size = strHello.length();

    //Creating Ptr using make_unique
    std::unique_ptr<char[]> pstrText;
    pstrText = make_unique<char[]>(size + 1); // Allocating +1 for [=11=]

    //Copying values to the new pointer
    int r = memcpy_s(pstrText.get(), size + 1, strHello.c_str(), size);

    //Printing
    std::cout << pstrText.get() << std::endl;
}

{ //Example 2
    //String to be copied
    std::string strHello = "HelloWorld2";
    int size = strHello.length();

    //Creating Ptr using make_unique
    std::unique_ptr<char[]> pstrText;
    pstrText = make_unique<char[]>(size);

    //Copying values to the new pointer
    int r = memcpy_s(pstrText.get(), size, strHello.c_str(), size);

    //Printing
    std::cout << pstrText.get() << std::endl;
}
{//Example 3

    //String to be copied
    std::string strHello = "HelloWorld3";
    int size = strHello.length();

    //Creating Ptr using make_unique
    std::unique_ptr<char[]> pstrText;
    pstrText = make_unique<char[]>(size + 1); //Allocating + 1

    //Copying values to the new pointer
    int r = memcpy_s(pstrText.get(), size, strHello.c_str(), size);

    //Printing
    std::cout << pstrText.get() << std::endl;
}

{//Example 4

    //String to be copied
    std::string strHello = "HelloWorld4";
    int size = strHello.length();

    //Creating Ptr using make_unique
    std::unique_ptr<char[]> pstrText;
    pstrText = make_unique<char[]>(size);

    //Copying values to the new pointer
    int r = memcpy_s(pstrText.get(), size + 1, strHello.c_str(), size); 

    //Printing
    std::cout << pstrText.get() << std::endl;
}

使用 VS 2013 Debug(Win32) 的输出如下:

HelloWorld1
HelloWorld2²²²²½½½½½½½½■
HelloWorld3
HelloWorld4²²²²½½½½½½½½■
  1. 如果示例 1 是正确的,为什么示例 3 也给出了正确的输出?
  2. 末尾的垃圾值表示什么?
  3. 为什么编译器没有抛出任何错误或异常?
  4. 在示例4中,为什么我们尝试在最后复制一个值但没有初始化时没有错误
  5. 在这种情况下,我们如何正确初始化智能指针?如果它是 BYTE 数组而不是 char,会有什么变化吗?

你需要知道的两件事:

首先是在 C++ 中 memcpy_s 是 Microsoft VC++ CRT 特定的扩展。它存在于 C 中(添加到 C11 标准中),但即便如此,Microsoft 对安全功能的实现也常常不遵循 C 标准。

第二件事,也是导致问题的原因,是最后一个参数是要复制的字节数。由于您只在此处指定 size ,因此您的调用不会复制字符串空终止符。您需要复制 size + 1 个字节:

int r = memcpy_s(pstrText.get(), size + 1, strHello.c_str(), size + 1);
//                                                               ^^^^
//                    Copy plus one, to also copy the null-terminator

If Example 1 is correct why does the Example 3 also give the correct output?

make_unique<char[]>(size + 1); 将所有 char 初始化为 0。示例 1 和示例 3 都不会覆盖它,因为它们分别复制了 size + 1 和 [=13= 中较小的一个]; sizesize 中较小的一个。 IE。他们都复制 size chars

What Does the garbage values at the end signify?

你的程序有未定义的行为。 std::ostream::operator<<(char *) 在这种情况下 读取字节直到它看到 0。

Why didn't the compiler throw any error or exception?

因为C++不安全。 整个程序 不受 C++ 规则的约束,而不是在访问数组外部时定义特定行为(例如抛出异常)。这叫做"Undefined Behaviour".

In Example 4 Why is there no error when we had tried to copy a value at the end but was not initialized

因为 C++ 不安全

How do we properly initialize a smart pointer in this case? Will anything change if it a BYTE array instead of char;

例子1和例子3都可以。但是,为什么不直接使用 std::string?