我知道从对象移动的是未指定但可破坏的状态,我通常知道这意味着他们可以拥有内存,文件句柄......
但我不知道是否允许从std::string
和std::vector
移动来拥有任何记忆。
例如,以下函数可能会泄漏内存,或者根据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 ));
}
注释:
我对ISO标准感兴趣,我知道最明显的
实现src
不应该在move
之后拥有任何内存,我
我对此代码的“合法”状态感兴趣。
我知道这里提供的代码不是用C ++编写代码的“正确”方式,它是 只是一个解释我的问题的例子
答案 0 :(得分:3)
没有;病态实现可以自由移动 - 构造任何特定的std字符串作为副本,只要操作不抛出就保留源。 (必须有一个长度超过这个长度,这不会发生遵守O(1)保证)。
std向量的迭代器失效规则更严格;事后,此举必须是病态上的邪恶才能拥有记忆。同样,即使分配失败,它也可能不会抛出。
如果这些都是不合理的可能性;但跳过破坏也是如此。
答案 1 :(得分:2)
标准中没有任何内容要求移动对象不再拥有任何资源。 (除了履约保证,但我不认为他们在这种情况下阻止了这种所有权。)
关于您的计划,请参阅[basic.life/4]:
对于具有非平凡析构函数的类类型的对象,程序不需要在重用或释放对象占用的存储之前显式调用析构函数;但是,如果没有显式调用析构函数或者如果没有使用delete-expression(5.3.5)来释放存储,则不应该隐式调用析构函数,并且任何程序都依赖于析构函数产生的副作用有未定义的行为。
这部分&#34;任何取决于副作用的程序&#34;并不像我们在标准文档中看到的那样精确,但它通常被解释为除了没有可观察行为的析构函数之外的任何其他内容。 。我们不知道库实现可能在其析构函数中为向量和字符串添加了什么(例如,它可以在调试模式下进行调试跟踪)。
所以我会说你的程序通过省略析构函数调用会导致未定义的行为,尽管还有一些讨论空间。