带有数组

时间:2018-03-13 13:57:04

标签: c++ c++11 visual-c++ move-semantics

尝试调试并理解一个似乎是移动构造函数的小问题,问题只出现在visual studio 2017 15.6.1,发布版本中。

这是代码(最小化以重现问题):

#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>

const size_t kSize = 16;

class Symbol
{
  public:
    explicit Symbol(const char *const name = nullptr)
     : name_{0}
    {
      if (name)
        std::memcpy(name_, name, strlen(name));
    }

    Symbol(const Symbol& other)
    {
       std::memcpy(name_, other.name_, sizeof(name_));
    }

    Symbol& operator=(const Symbol& other)
    {
       if (this != &other)
         std::memcpy(name_, other.name_, sizeof(name_));

       return *this;
    }

    Symbol(Symbol&& other) noexcept
    {
       std::memcpy(name_, other.name_, sizeof(name_));
       std::memset(other.name_, 0, sizeof(other.name_));
    }

    const char* GetSymbolName(void) const { return name_; }

  private:
    char name_[kSize];
 };

struct MyTestMessage
{
   Symbol   symbol;
   int32_t  type;
   int32_t  other;
   int32_t  status;
   int32_t  reserved[5];

   MyTestMessage() = default;
   MyTestMessage(const MyTestMessage& msg) = default;
   MyTestMessage(MyTestMessage&& msg) = default;

   /*
   MyTestMessage(MyTestMessage&& msg) noexcept
     : symbol(std::move(msg.symbol))
  {
    status = msg.status;
    other = msg.other;
    type = msg.type;
  }*/
};

void Print(const std::vector<MyTestMessage>& data)
{
   std::cout << "------------" << std::endl;
   std::for_each(data.cbegin(), data.cend(), [](const MyTestMessage& msg)
 {
    std::cout <<msg.symbol.GetSymbolName() << " " << msg.other << " " << 
              msg.status << " " << msg.type << std::endl;
  });
}

int main()
{
  std::vector<MyTestMessage> my_test;

  MyTestMessage msg;
  msg.other = 5;
  msg.symbol = Symbol("TEST");
  msg.type = 5;
  msg.status = 5;

  my_test.push_back(msg);
  Print(my_test);
  my_test.push_back(msg);
  Print(my_test);

  return 0;

}

或者你可以在这里获取代码coliru link

以下是visual studio发布版本的输出:

TEST 5 5 5

TEST 5 5 0

TEST 5 5 5

问题是0来自哪里?

两种“修复它”的方法:

  • 为MyTestMessage添加移动构造函数,此时已注释掉。

  • 或者评论std :: memset(other.name _,0,sizeof(other.name_));在符号移动构造函数中。

删除MyTestMessage中的任何数据成员(类型,其他,状态)后问题消失。

但我不相信其中任何一个是正确的。

我在这里做错了什么想法?

修改 编译器版本是visual studio 2017 15.6.1 实际上设法找到改变输出的编译器设置: 如果“Enable IntrinsicFunctions”设置为:Yes(/ Oi)问题是可重现的,如果设置为No,则按预期工作。

更新 微软已经做出回应,它确实是一个错误,它已经在VS2017 15.7 Preview 1中得到修复。

2 个答案:

答案 0 :(得分:0)

代码没有错。

这似乎是VS中的一个错误。据推测已修复VS2017 15.7预览1。

答案 1 :(得分:-3)

  

我在这里做错了什么想法?

当您不需要时,您会使用指针。只需使用:

 struct Symbol { char name[kSize]; };

你的例子中有什么。 ......但是,坦率地说,除非有充分的理由不这样做,坚持std::string