首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::move - std::string -内部指针

std::move - std::string -内部指针
EN

Stack Overflow用户
提问于 2013-04-07 19:01:24
回答 3查看 1.2K关注 0票数 3

我很惊讶s和s2内部指向"sample“的指针不相等,这是怎么解释的?

代码语言:javascript
复制
#include <string>
#include <cassert>

int main()
{
    std::string s("sample"); 

    std::string s2(std::move(s)); 

    assert(
        reinterpret_cast<int*>(const_cast<char*>(s.data())) ==
        reinterpret_cast<int*>(const_cast<char*>(s2.data()))
        ); // assertion failure here    

    return 1;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-07 19:03:55

为什么你认为它们应该是一样的呢?您正在使用s的move构造函数从它构造s2。这会将数据所有权从s转移到s2,并使s处于“空”状态。该标准没有详细说明这需要什么,但在此之后访问s的数据(没有事先重新分配)是未定义的。

一个非常简化(和不完整)的string版本可能如下所示:

代码语言:javascript
复制
class string {
    char* buffer;

public:

    string(char const* from)
        : buffer(new char[std::strlen(from) + 1])
    {
        std::strcpy(buffer, from);
    }

    string(string&& other)
        : buffer(other.buffer)
    {
        other.buffer = nullptr; // (*)
    }

    ~string() {
        delete[] buffer;
    }

    char const* data() const { return buffer; }
};

我希望这能说明为什么data()成员不平等。如果我们省略了标记为(*)的行,我们将在main的末尾删除两次内部缓冲区:一次用于s,一次用于s2。重置buffer指针可以确保这种情况不会发生。

票数 3
EN

Stack Overflow用户

发布于 2013-04-07 19:04:23

每个std::string都有它自己指向的缓冲区。您将一个从另一个移动到另一个并不会使它共享一个缓冲区。初始化s2时,它将从s手中接管缓冲区并成为该缓冲区的所有者。为了避免s“拥有”相同的缓冲区,它简单地将s的缓冲区设置为一个新的空缓冲区(现在由s负责)。

从技术上讲,也涉及到一些优化,很可能没有一个真正的缓冲区显式地分配给空字符串或非常小的字符串,但是std::string的实现将使用std::string本身的一部分内存,这通常被称为STL语言中的小字符串优化。

还要注意,s已经被移走了,所以你的代码访问它的数据是非法的,这意味着它可能会返回任何东西。

票数 3
EN

Stack Overflow用户

发布于 2013-04-07 19:05:04

在将其值替换为某个已知值之前,不应使用moved-from string

库代码需要在参数中保留一个有效值,但除非类型或函数另有说明,否则对得到的参数值没有其他约束。这意味着通常最明智的做法是避免再次使用moved from参数。如果必须再次使用它,请确保在执行此操作之前使用已知值重新初始化它。

库可以将它想要的任何内容插入到字符串中,但很可能最终得到的是一个空字符串。这就是运行example from cppreference所产生的结果。然而,人们不应该期望在一个移出的对象中找到任何特别的东西。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15861620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档