Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.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++ 从字符串和向量中移动是否需要不拥有任何堆内存?_C++_Move Semantics - Fatal编程技术网

C++ 从字符串和向量中移动是否需要不拥有任何堆内存?

C++ 从字符串和向量中移动是否需要不拥有任何堆内存?,c++,move-semantics,C++,Move Semantics,我知道从对象中移动的对象处于未指定但可破坏的状态,我通常知道这意味着它们可以拥有内存、文件句柄。。。 但我不知道是否允许从std::strings和std::vectors中移动来拥有任何内存 例如,下面的函数可能会泄漏内存,还是按照C++标准? void f(){ std::aligned_storage_t<sizeof(std::string), alignof(std::string)> memory; std::string& src = *new

我知道从对象中移动的对象处于未指定但可破坏的状态,我通常知道这意味着它们可以拥有内存、文件句柄。。。 但我不知道是否允许从
std::string
s和
std::vector
s中移动来拥有任何内存

例如,下面的函数可能会泄漏内存,还是按照C++标准?

void f(){
    std::aligned_storage_t<sizeof(std::string), alignof(std::string)> memory;
    std::string& src = *new (&memory) std::string ("98->03->11->14->17->20");
    std::string dest(std::move(src ));
}
void f(){
std::对齐的存储存储器;
std::string&src=*新建(&memory)std::string(“98->03->11->14->17->20”);
std::stringdest(std::move(src));
}
注:

  • 我对ISO标准感兴趣,我知道这是最明显的 实现
    src
    移动后不应拥有任何内存,I
    我对本规范的“法律”地位感兴趣

  • 我知道这里提出的代码不是C++中的“正确”方式,而是 只是一个例子来解释我的问题

  • 我问的是关于std::string和std::vector的问题,我知道这不是一般的问题

否;病理学实现可以自由地将任何特定的std字符串作为副本进行移动和构造,只要操作不抛出,就可以不使用源代码。(必须有一个长度,超过该长度时,不符合O(1)保证)

std向量的迭代器无效规则更严格;这一举动必然是病态的邪恶,会影响到后来的记忆。同样,即使分配失败,它也可能不会抛出


如果这些都是不合理的可能性;但是跳过销毁也是如此。

标准中没有要求从对象移动到不再拥有任何资源的内容。(除了性能保证,但我不认为它们阻止了这种情况下的所有权)

关于您的计划,请参见[basic.life/4]:

对于具有非平凡析构函数的类类型的对象,在重用或释放该对象占用的存储之前,程序不需要显式调用析构函数;但是,如果没有显式调用析构函数,或者如果没有使用删除表达式(5.3.5)来释放存储,则不应隐式调用析构函数,并且依赖于析构函数产生的副作用的任何程序都具有未定义的行为

“任何依赖于副作用的程序”这一部分并不像我们在标准文件中看到的那样精确,但它通常被解释为“除了没有可观察行为的析构函数之外的任何东西”。我们不知道库实现可能在向量和字符串的析构函数中放入了什么(例如,它可能在调试模式下具有调试跟踪)


因此,我想说,您的程序由于忽略析构函数调用而导致未定义的行为,尽管还有一些争议。

如果moved from
std::string
“拥有”任何内存,那么当moved from对象被销毁时,它将被释放。每一个被建造的物体都必须被摧毁。“从对象移动”也不例外。“从中移动”对象是否实际拥有任何内存(在其自身销毁时需要释放)尚未确定。显示的代码是未定义的行为,因为对齐存储中的
std::string
对象从未被销毁。要简单地修复它,请显式调用其析构函数。现在它是被定义的行为(除非抛出的异常在不销毁对象的情况下离开此范围。我们所知道的只是它处于有效但未指定的状态。尽管我很努力,我无法想象为什么人们有理由不直接调用析构函数,按照通常的布局构造/销毁规范,而不管是否已执行移动。我明白了关于
std::vector
std::basic_string
,没有可想象的标准支持例外。这类似于询问构造空
vector
string
而不销毁它是否会泄漏。“拥有内存”与标准中使用或描述的任何术语都不对应。(有拥有和不拥有的智能指针和
std::function
对象,但“不拥有”的含义也并不意味着你在这里要问什么。)想到一件事——实现“小字符串优化”(SSO)的STL库对于
std::string
。当启用SSO的字符串包含小内容时,字符数据不会存储在动态内存中,因此无法移动到另一个字符串对象。只能将内容从一个缓冲区复制到另一个缓冲区。从中移动的字符串保留其内存缓冲区的所有权,尽管其
大小
重置为0 d"动"起来。对于非SSO字符串,以及内容长于SSO缓冲区的字符串,内存是动态分配的,因此可以在字符串对象之间转移所有权。恒定时间复杂性保证禁止无条件复制所有字符串进行移动构造。@user23当然可以,但它可以复制长度不超过527432的所有字符串。任何基于堆的复制品已经是病态的了;那么为什么仅仅停留在精神错乱上呢?但这一点很好;编辑在。