相关疑难解决方法(0)

移动的向量是否总是空的?

我知道通常标准对已经移动的值的要求很少:

N3485 17.6.5.15 [lib.types.movedfrom]/1:

可以从(12.8)移动C++标准库中定义的类型的对象.可以显式指定或隐式生成移动操作.除非另有规定,否则此类移动物体应置于有效但未指定的状态.

我找不到任何与vector此明确排除的内容.但是,我无法想出一个理智的实现,导致向量不为空.

是否有一些标准需要我缺少或者类似于在C++ 03中作为连续缓冲区处理basic_string

c++ vector language-lawyer move-semantics c++11

36
推荐指数
2
解决办法
6697
查看次数

从std :: string中不必要地清空move-from

std::string即使原始存储的字符串很短并且应用了短字符串优化,libstdc ++和libc ++也会使对象变为空.在我看来,这种清空会产生额外的和不必要的运行时开销.例如,这是std::basic_stringlibstdc ++ 的移动构造函数:

basic_string(basic_string&& __str) noexcept
  : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator())) {
    if (__str._M_is_local()) 
      traits_type::copy(_M_local_buf, __str._M_local_buf, _S_local_capacity + 1);
    else {
      _M_data(__str._M_data());
      _M_capacity(__str._M_allocated_capacity);
    }
    _M_length(__str.length());
    __str._M_data(__str._M_local_data());  // (1)
    __str._M_set_length(0);                // (2)
  }
Run Code Online (Sandbox Code Playgroud)

(1)是一个在短字符串情况下无效的赋值,因为数据已经设置为本地数据,所以我们只需为指针指定与之前分配的值相同的值.

(2)清空字符串设置字符串大小并重置本地缓冲区中的第一个字符,据我所知,标准不要求.

通常,库实现者尝试尽可能高效地实现标准(例如,删除的内存区域不会被清零).我的问题是,如果可能有任何特殊原因导致移动的字符串被清空,即使它不是必需的,也会增加不必要的开销.其中,可以很容易地消除,例如:

basic_string(basic_string&& __str) noexcept
  : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator())) {
    if (__str._M_is_local()) {
      traits_type::copy(_M_local_buf, __str._M_local_buf, _S_local_capacity + 1);
      _M_length(__str.length());
    }
    else {
      _M_data(__str._M_data());
      _M_capacity(__str._M_allocated_capacity);
      _M_length(__str.length());
      __str._M_data(__str._M_local_data());  // (1)
      __str._M_set_length(0);                // (2)
    }
  }
Run Code Online (Sandbox Code Playgroud)

c++ string libstdc++ move-semantics

9
推荐指数
1
解决办法
275
查看次数

std::move(std::string) 不使传递的参数为空状态

我有点困惑为什么std::move(std::string)不将传递的std::string参数设置为空状态(我的意思是std::string大小为 0 及其内部缓冲区nullptr在调用后指向std::move(std::string))。这是示例代码

#include <iostream>
#include <string>

void print(std::string& str) {
    std::cout << "lref\n";
    std::cout << str << "\n" << std::endl;
}

void print(const std::string& str) {
    std::cout << "const lref\n";
    std::cout << str << "\n" << std::endl;
}

void print(std::string&& str) {
    std::cout << "rref\n";
    std::cout << str << "\n" << std::endl;
}

int main() {
    std::string str_a = "Hello, ";
    std::string str_b = "world!";
    
    print(str_a);
    print(str_b);
    print(str_a + …
Run Code Online (Sandbox Code Playgroud)

c++

2
推荐指数
1
解决办法
556
查看次数