Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将字符串从stringstream移动到字符串向量中_C++_String_C++11_Stl_Stringstream - Fatal编程技术网

C++ 将字符串从stringstream移动到字符串向量中

C++ 将字符串从stringstream移动到字符串向量中,c++,string,c++11,stl,stringstream,C++,String,C++11,Stl,Stringstream,我有一个std::stringstream ss和一个std::vector列表 我想向后推(或向后放置)ss到列表 如何以最佳方式避免额外复制ss的支持字符串 我的意图是立即运行ss.clear(),因为我将重新填充它(稍后附加到列表中) 可能的选择: list.emplace\u back(std::move(ss.str()) list.emplace\u back(ss.str()) list.push_-back(std::move(ss.str()) 列表。向后推(ss.str())

我有一个
std::stringstream ss
和一个
std::vector列表

我想
向后推
(或
向后放置
ss
列表

如何以最佳方式避免额外复制
ss
的支持字符串

我的意图是立即运行
ss.clear()
,因为我将重新填充它(稍后附加到
列表中)

可能的选择:

  • list.emplace\u back(std::move(ss.str())
  • list.emplace\u back(ss.str())
  • list.push_-back(std::move(ss.str())
  • 列表。向后推(ss.str())
  • 在每种情况下会发生什么?在每种情况下,
    ss
    中会保留什么?(在任何情况下我都会扔掉它)

    导致我不确定该做什么的原因是。尽管我没有将stringstreams移动到另一个容器中,但我现在特别担心的是能否将构建为stringstream的字符串(可能是巨大的)移动到字符串容器的后面。显然如果
    str()
    的实现方式会导致一些复制或转换,这是不可避免的,但我希望生成的代码能够以恒定的时间将其填充到向量的后面

    我研究了
    str()
    的实现:

    模板
    基本字符串
    基本字符串buf::str()常量
    {
    如果(\uuuuu模式\uiOS\uU基::输出)
    {
    如果(uuhm_uupptr())
    __hm_=此->pptr();
    返回字符串类型(this->pbase(),\uuuuhm,\uuuuu str.get\u分配器());
    }
    else if(uuuu mode_uuu&ios_ubase::in)
    返回字符串类型(this->eback(),this->egptr(),uuu str_u.get_分配器());
    返回字符串类型(uu str_u.get_分配器());
    } 
    

    复制函数返回值在默认情况下已经是std::moved.ie

    std::string herp() { return string("lalalalala"); }
    
    std::string derp (herp ());
    
    将使用derp的std::string移动构造函数

    正如您在下面的代码中所看到的,将使用移动分配操作符。 在内部,字符串自身的
    操作符=(&&&)
    将与字符串
    ss.str()交换。将返回

    #include <iostream>
    #include <sstream>
    #include <string>
    
    using namespace std;
    
    class Herp {
        string internal;
        public:
            const Herp& operator=(const string& s)
            {
                cout<<"Standard initialize operator\n";
                internal = s;
                return *this;
            }
            const Herp& operator=(string&& s)
            {
                cout<<"Move initialize operator\n";
                internal = s;
                return *this;
            }
    };
    
    int main()
    {
        Herp a;
        stringstream ss;
        ss<<string("abcdef");
        a = ss.str();
        return 0;
    }
    
    #包括
    #包括
    #包括
    使用名称空间std;
    班主任{
    字符串内部;
    公众:
    常量Herp和运算符=(常量字符串和运算符)
    {
    
    cout对于这种情况,想法如下:
    1) ss返回一个字符串,该字符串是stringstream文本的内部表示形式的副本,字符串有一个内部缓冲区和一个指针(这就是为什么move对字符串有意义,尽管也有)
    2) 由于返回的字符串在传递到emplace back时是一个临时值,它将在vector中移动一个字符串对象,因此不会有内部缓冲区的副本(只有指针和一些整数在临时字符串和新字符串之间交换,这是非常便宜的)。这里几乎同样适用于push_back

    所以

  • list.emplace_back(std::move(ss.str())
  • list.emplace_back(ss.str())
  • list.push_back(std::move(ss.str())
  • list.push_back(ss.str())

  • 所有案例都必须做几乎相同的事情(这意味着它们不会复制临时字符串缓冲区)。一如既往地分析并看看有什么更好,但我怀疑在这种情况下是否有明显的区别。

    正如前面所说的,所有四个选项最终都做相同的事情,并且都是最佳的-它们移动
    str()返回的临时字符串
    (这是一个右值,因此
    和&
    推回的重载将应用)到向量的后面。
    emplace\u back
    在您有一组参数要传递给
    value\u type
    的构造函数时非常有用。请考虑:

    std::vector<std::pair<std::string, std::string>> vec;
    
    vec.push_back(std::make_pair("Hey", "You")); // a temporary pair is created here
    
    vec.emplace_back("Hey", "You");  // arguments are forwarded to the constructor of
                                     // pair which is constructed in place
    

    你不需要调用
    std::move()
    ,因为
    ss.str()
    已经返回了一个右值。如果我没有弄错的话,我需要从中提取一个x值。
    emplace\u back
    也许可以强制这样做?或者什么?我的理解是模糊的。(我认为这也可能是错误的。Emplace_back将使用args在适当的位置构建某些内容以传递给类型的ctor…这实际上是一个复制操作。不需要。)ss.str()是一个副本右值,由std::vector的移动副本移动operator@Julius什么是拷贝值?rValk?如果其他人读到这个,同样会被EffisteBead弄混淆,这里有一个很好的讨论:谢谢,这对我来说仍然是个黑魔法,我最近一直在写很多C++。还有很多要学习。现在,我是~ 80%肯定A。关于这一点,但请验证您是否愿意:我应该使用
    emplace\u back
    ,然后我可以跳过
    std::move
    ,因为它基本上只是转发
    ss.str()
    移动到
    std::string的移动向量。是吗?使用
    push_back
    是否也会移动它?如果我想将它推到向量,但我仍然想要访问它(即,我实际上想要一个副本…),这与push back一起工作。emplace back被特别称为不使用move操作符,如()哈?那么这是向后的吗?
    emplace\u back
    复制,
    push\u back
    移动?我他妈的该如何从阅读文档中做出这个推断?对于
    push\u back
    ,它说只有当T满足MoveInsertable的要求时才使用第二个ctor,我不知道
    ss.str()的值
    符合这个标准。因此这个问题。对于
    安置回
    ,好的,回到我关于安置回的原始结论,即我不能使用它(因为我想移动,而不是复制或构造)你能看看我在@Julius答案的评论上贴的colirus吗?它们表明发生了一个拷贝。也许有一个不可避免的拷贝总是作为
    str()
    的一部分发生?也许这是SSO的结果。每当一个新的临时字符串出现时,ss.str()就会返回。在示例代码中,你调用了ss.st
    std::vector<std::pair<std::string, std::string>> vec;
    
    vec.push_back(std::make_pair("Hey", "You")); // a temporary pair is created here
    
    vec.emplace_back("Hey", "You");  // arguments are forwarded to the constructor of
                                     // pair which is constructed in place
    
    list.emplace_back(std::move(ss).str());