C++ :为什么我没有调用“std::uninitialized_copy”在职的?

发布于 2024-10-15 17:31:09 字数 1527 浏览 2 评论 0原文

我构建了一个简单的类,该类应该模仿 std::string 类的功能(作为练习!):

#ifndef _STR12_1_H
#define _STR12_1_H

#include <string>
#include <iostream>

class Str12_1
{
public:

    typedef char* iterator;
    typedef const char* const_iterator;
    typedef long size_type;


    Str12_1();
    Str12_1(const Str12_1& str);
    Str12_1(const char *p);
    Str12_1(const std::string& s);

    size_type size() const;

    //Other member functions


private:
    iterator first;
    iterator onePastLast;
    iterator onePastAllocated;
};

为了避免与“new”相关的开销(并增加我对 < memory> 标头),我选择使用库的分配器模板类为我的字符串分配内存。这是我在复制构造函数中使用它的一个示例:

#include <memory>
#include <algorithm>

using std::allocator;
using std::raw_storage_iterator;
using std::uninitialized_copy;


Str12_1::Str12_1(const Str12_1& str)
{
    allocator<char> charAlloc;
    first = charAlloc.allocate(str.size());
    onePastLast = onePastAllocated = first + str.size();
    *onePastLast = '\0';

    raw_storage_iterator<char*, char> it(first);

    uninitialized_copy(str.first, str.onePastLast, it);


}

编译器不断告诉我“uninitialized_copy”行上的两个错误,这两个错误都返回到库中的标头:

error: invalid conversion from 'char' to 'char*'

error: no match for 'operator!=' in '__first != __last'

问题是我不明白该错误在哪里line 从 char 到 char* 的转换是,以及为什么两个相同类型的指针(str.first、str.onePastLast)不能与“!=”进行比较。

我可以使用“new”,但如前所述,我想练习 。那么有人可以告诉我为什么这不起作用吗?

I building a simple class that is supposed to mimic the functionality of the std::string class (as an exercise!):

#ifndef _STR12_1_H
#define _STR12_1_H

#include <string>
#include <iostream>

class Str12_1
{
public:

    typedef char* iterator;
    typedef const char* const_iterator;
    typedef long size_type;


    Str12_1();
    Str12_1(const Str12_1& str);
    Str12_1(const char *p);
    Str12_1(const std::string& s);

    size_type size() const;

    //Other member functions


private:
    iterator first;
    iterator onePastLast;
    iterator onePastAllocated;
};

In order to avoid the overhead associated with "new" (and to increase my familiarity with the <memory> header), i've opted to use the library's allocator template class to allocate memory for my string. Here is an example of my use of it in the copy constructor:

#include <memory>
#include <algorithm>

using std::allocator;
using std::raw_storage_iterator;
using std::uninitialized_copy;


Str12_1::Str12_1(const Str12_1& str)
{
    allocator<char> charAlloc;
    first = charAlloc.allocate(str.size());
    onePastLast = onePastAllocated = first + str.size();
    *onePastLast = '\0';

    raw_storage_iterator<char*, char> it(first);

    uninitialized_copy(str.first, str.onePastLast, it);


}

The compiler keeps telling me two errors on the "uninitialized_copy" line which both lead back to headers in the library, :

error: invalid conversion from 'char' to 'char*'

error: no match for 'operator!=' in '__first != __last'

The problem is that I don't understand where on that line the conversion from char to char* is, and why two pointers of the same type (str.first, str.onePastLast) cannot be compared with "!=".

I could use "new", but as stated before, I want to get practice with <memory>. So can someone tell me why this isn't working?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自由如风 2024-10-22 17:31:09

查看标准 raw_storage_iterator 不会将 typedef value_type 设为 T,而是使用 void

template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void,void,void>
                                      ^^^^

uninitialized_copy 必须使用该 typedef:

template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);

效果:

for (; first != last; ++result, ++first)
::new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

在您的代码中,在进行所有替换之后,这会导致:

new (...&*result) void (*first);
                  ^^^^^^^^^^^^^
                 invalid use here

由此您可以得出结论,这两者永远不会一起工作。

如果您想使用raw_storage_iterator,那么将它传递给std::copy应该没问题,因为所有的魔法都发生在operator=(const T& ) 过载。

如果您认为这对于像 char 这样的原语是必要的,您可以使用 new char[x] 进行分配(注意!终止 NUL)并使用 进行复制strcpy

Looking at the standard raw_storage_iterator does not typedef value_type to be T, but it's void instead:

template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void,void,void>
                                      ^^^^

whereas uninitialized_copy has to use that typedef:

template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);

Effects:

for (; first != last; ++result, ++first)
::new (static_cast<void*>(&*result))
typename iterator_traits<ForwardIterator>::value_type(*first);
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In your code, after all substitutions, this leads to:

new (...&*result) void (*first);
                  ^^^^^^^^^^^^^
                 invalid use here

From that you can conclude that those two were never meant to work together.

If you want to use raw_storage_iterator, then it should be fine to pass it to std::copy since all the magic happens in the operator=(const T&) overload.

If you think any of this is necessary for a primitive like char where you might just allocate with new char[x] (NB! terminating NUL) and copy with strcpy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文