所以这里有一个小测试程序:
#include <string>
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
  Test(const std::vector<int>& a_, const std::string& b_)
    : a(std::move(a_)),
      b(std::move(b_)),
      vBufAddr(reinterpret_cast<long long>(a.data())),
      sBufAddr(reinterpret_cast<long long>(b.data()))
  {}
  Test(Test&& mv)
    : a(std::move(mv.a)),
      b(std::move(mv.b)),
      vBufAddr(reinterpret_cast<long long>(a.data())),
      sBufAddr(reinterpret_cast<long long>(b.data()))
  {}
  bool operator==(const Test& cmp)
  {
    if (vBufAddr != cmp.vBufAddr) {
      std::cout << "Vector buffers differ: " << std::endl
        << "Ours: " << std::hex << vBufAddr << std::endl
        << "Theirs: " << cmp.vBufAddr << std::endl;
      return false;
    }
    if (sBufAddr != cmp.sBufAddr) {
      std::cout …Run Code Online (Sandbox Code Playgroud) 在这样的代码中:
#include <iostream> 
#include <initializer_list>
#include <string>
struct A 
{
  A() { std::cout << "2" << std::endl; }
  A(int a) { std::cout << "0" << std::endl; }
  A(std::initializer_list<std::string> s) { std::cout << "3" << std::endl; }
  A(std::initializer_list<int> l) { std::cout << "1" << std::endl; } 
};
int main() 
{ 
 A a1{{}}; 
} 
Run Code Online (Sandbox Code Playgroud)
为什么调用std::initializer_list<int>构造函数的规范?如果我们定义构造函数,它会产生歧义编译错误std::initializer_list<double>.这种结构的规则是什么?为什么std::initializer_list数字作为模板参数如此具体?
这里我有一些简单的代码:
#include <iostream>
#include <cstdint>
    int main()
    {
         const unsigned char utf8_string[] = u8"\xA0";
         std::cout << std::hex << "Size: " << sizeof(utf8_string) << std::endl;
          for (int i=0; i < sizeof(utf8_string); i++) {
            std::cout << std::hex << (uint16_t)utf8_string[i] << std::endl;
          }
    }
Run Code Online (Sandbox Code Playgroud)
我在这里看到 MSVC 和 GCC 的不同行为。MSVC 认为"\xA0"未编码的 unicode 序列,并将其编码为 utf-8。所以在 MSVC 中,输出是:
C2A0
这是在 utf8 unicode 符号中正确编码的U+00A0。
但是在 GCC 的情况下,什么也没有发生。它将字符串视为简单的字节。即使我u8在字符串文字之前删除也没有变化。
这两种编译器编码与输出UTF8C2A0如果字符串设定为:u8"\u00A0";
为什么编译器的行为不同,哪个实际上是正确的?
用于测试的软件:
海湾合作委员会 8.3.0
MSVC 19.00.23506
C++ 11
假设我有界面:
class MyInterface
{
public:
    virtual ~MyInterface() = default;
    virtual void DoSomething(const MyType& a, const MyTypeB& b);
};
Run Code Online (Sandbox Code Playgroud)
我想要的是如果任何函数参数是右值或左值引用,则允许使用移动语义。
我不想要的是像这样定义接口:
class MyInterface
{
public:
    virtual ~MyInterface() = default;
    virtual void DoSomething(const MyType& a, const MyTypeB& b);
    virtual void DoSomething(MyType&& a, const MyTypeB& b);
    virtual void DoSomething(const MyType& a, MyTypeB&& b);
    virtual void DoSomething(MyType&& a, MyTypeB&& b);
};
Run Code Online (Sandbox Code Playgroud)
如果向方法中添加更多参数,组合数学会变得更糟。
因此,在实现中,如果我传递了右值,我基本上想移动参数,否则进行复制。
标准库中有std::forward,但它与所谓的“转发引用”一起使用,这需要模板,并且在虚拟方法中不可能有模板参数。
有没有什么方法可以做到这一点,同时保留接口基类型的目的,并且不会使接口本身变得如此膨胀?
我已经研究了一些库的代码,并注意到那里的调用calloc后面跟着memset分配的块calloc.我发现这个问题有一个非常全面的答案,关于calloc和malloc+ 之间的差异,并在分配存储之前memset调用memset:
我仍然无法理解的是为什么人们会这样做.这项业务有什么好处?
上面提到的代码示例库:
light_pcapng_file_info *light_create_default_file_info()
{
    light_pcapng_file_info *default_file_info = calloc(1, sizeof(light_pcapng_file_info));
    memset(default_file_info, 0, sizeof(light_pcapng_file_info));
    default_file_info->major_version = 1;
    return default_file_info;
}
Run Code Online (Sandbox Code Playgroud)
分配结构的代码(每个数组包含32个元素):
typedef struct _light_pcapng_file_info {
    uint16_t major_version;
    uint16_t minor_version;
    char *file_comment;
    size_t file_comment_size;
    char *hardware_desc;
    size_t hardware_desc_size;
    char *os_desc;
    size_t os_desc_size;
    char *user_app_desc;
    size_t user_app_desc_size;
    size_t interface_block_count;
    uint16_t link_types[MAX_SUPPORTED_INTERFACE_BLOCKS];
    double timestamp_resolution[MAX_SUPPORTED_INTERFACE_BLOCKS];
} light_pcapng_file_info;
Run Code Online (Sandbox Code Playgroud)
编辑:
除了接受的答案,我想提供一些我的同事指出的信息.glibc中有一个错误,有时会阻止calloc将内存清零.这是链接:https: //bugzilla.redhat.com/show_bug.cgi?id = 1293976
案例链接移动时的实际错误报告文本:
glibc:calloc()返回非零内存 …
我这里有代码:
#include <string>
#include <iostream>
#include <initializer_list>
template <typename T>
class Test
{
public:
  Test(std::initializer_list<T> l)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test(const Test<T>& copy)
  {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
  Test(Test&&) = delete;
  Test() = delete;
};
void f(const Test<Test<std::string>>& x)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void f(const Test<std::string>& x)
{
  std::cout << __PRETTY_FUNCTION__ << std::endl;
  f(Test<Test<std::string>>{x});
}
int main()
{
  Test<std::string> t1 {"lol"};
  f(t1);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)
我尝试用我的linux mint 19上的GCC 7.3.0编译这个命令:
g ++ -std …
我在 C 中有 2 个函数:
void func1(unsigned char x)
{
    unsigned char a[10][5];
    a[0][0] = 1;
    a[9][4] = 2;
}
void func2(unsigned char x)
{
    unsigned char a[10][5];
    a[0][0] = 1;
    a[9][4] = 2;
    unsigned char b[10];
    b[0] = 4;
    b[9] = 5;
}
Run Code Online (Sandbox Code Playgroud)
编译:
gcc 7.3 x86-64
-O0 -g
操作系统:
16.04.1-Ubuntu x86-64
生产的英特尔功能组装:
func1(unsigned char):
  pushq %rbp
  movq %rsp, %rbp
  movl %edi, %eax
  movb %al, -68(%rbp)
  movb $1, -64(%rbp)
  movb $2, -15(%rbp)
  nop
  popq %rbp
  ret
func2(unsigned char):
  pushq …Run Code Online (Sandbox Code Playgroud) 使用默认删除器是否安全std::unique_ptr?
我想这样使用它:
uint8_t* binaryData = new uint8_t[binaryDataSize];
std::unique_ptr<uint8_t> binPtr(binaryData);
Run Code Online (Sandbox Code Playgroud)
所以默认的删除器std::unique_ptr看起来像这样:
template<typename _Up>
typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
operator()(_Up* __ptr) const
{
    static_assert(sizeof(_Tp)>0,
                  "can't delete pointer to incomplete type");
    delete [] __ptr;
}
Run Code Online (Sandbox Code Playgroud)
从我的观点来看,使用由原始指针分配的原始指针是new[]安全的,而不是由分配的原始指针安全std::malloc.我错过了什么吗?有更好的解决方案吗?