小编Kno*_*abe的帖子

对于默认构造函数和析构函数,"= default"与"{}"有什么不同?

我最初发布这个只是关于析构函数的问题,但现在我正在添加对默认构造函数的考虑.这是原始问题:

如果我想给我的类一个虚拟的析构函数,但是与编译器生成的析构函数相同,我可以使用 =default:

class Widget {
public:
   virtual ~Widget() = default;
};
Run Code Online (Sandbox Code Playgroud)

但似乎我可以通过使用空定义减少输入来获得相同的效果:

class Widget {
public:
   virtual ~Widget() {}
};
Run Code Online (Sandbox Code Playgroud)

这两种定义的行为方式有何不同?

根据此问题的回复,默认构造函数的情况似乎相似.鉴于析构函数的" =default"和" {}"之间的含义几乎没有差异,默认构造函数的这些选项之间的含义几乎没有差别吗?也就是说,假设我想创建一个类型,其中该类型的对象将被创建和销毁,为什么我要说

Widget() = default;
Run Code Online (Sandbox Code Playgroud)

代替

Widget() {}
Run Code Online (Sandbox Code Playgroud)

如果在原始帖子违反某些SO规则后延长此问题,我深表歉意.为默认构造函数发布一个几乎完全相同的问题让我觉得不太理想.

c++ user-defined-functions default-constructor deleted-functions c++11

151
推荐指数
3
解决办法
3万
查看次数

为什么在C++ 11或C++ 14中没有进驻迭代器?

C++ 98有front_inserter,back_inserterinserter,但在C++ 11或草案C++ 14中似乎没有任何这些版本.有没有我们不能有任何技术原因front_emplacer,back_emplaceremplacer

c++ iterator stl c++11 c++14

46
推荐指数
2
解决办法
4321
查看次数

为什么在C++ 14中运行时大小的数组和std :: dynarray?

草案C++ 14包括运行时大小的数组和std::dynarray容器.从我所知道的,两者之间的唯一真正的区别在于std::dynarray有一个STL接口(例如begin,end,size,等),同时运行时大小的数组没有.那么为什么C++ 14需要它们呢?

我知道运行时大小的数组是核心语言的std::dynarray一部分,同时也是标准库的一部分,但是该提议std::dynarray清楚地表明作者希望编译器在许多情况下能够提供特殊支持,std::dynarray以便它可以高效尽可能地,即,与运行时大小的数组一样高效.因此,语言/库的区别似乎有点人为.

那么,为什么C++ 14需要两个运行时大小的数组std::dynarray呢?并且鉴于它std::dynarray具有更丰富的(STLified)接口,为什么不只是删除运行时大小的数组,假设std::dynarray可以以相同的运行时效率实现?

澄清

当我谈到"运行时大小的数组"时,我指的是N3639中描述的新的C++ 14核心语言特性,而不是传统的C数组或VLA或C++ 11中的任何内容.

c++ dynamic-arrays dynarray c++14

45
推荐指数
1
解决办法
9734
查看次数

为什么容器移动赋值运算符不会超出?

我注意到std::string(真的std::basic_string是)移动赋值运算符是 noexcept.这对我来说很有意义.但后来我发现,没有一个标准集装箱(例如std::vector,std::deque,std::list,std::map)宣布其移动赋值操作符noexcept.这对我来说没什么意义.std::vector例如,A 通常实现为三个指针,并且指针当然可以移动分配而不会抛出异常.然后我想也许问题是移动容器的分配器,但std::string也有分配器,所以如果这是问题,我希望它会影响std::string.

那么为什么std::string移动赋值运算符noexcept,但标准容器的移动赋值运算符不是?

c++ c++11

41
推荐指数
2
解决办法
3697
查看次数

哪个std :: async实现使用线程池?

使用std::async而不是手动创建std::thread对象的优点之一应该是std::async可以使用封面下的线程池来避免超额配置问题.但是哪些实现这样做?我的理解是微软的实现确实如此,但这些其他async实现呢?

  • Gnu的libstdc ++
  • Gnu的libc ++
  • Just Software的库
  • 提升(为boost::thread::async,不std::async)

感谢您提供的任何信息.

c++ multithreading c++11 stdasync

39
推荐指数
1
解决办法
1万
查看次数

有关初始化非本地静态的规则是什么?

假设我有一个类,其唯一目的是在构造对象时产生的副作用(例如,使用工厂注册类):

class SideEffectCauser {
public:
  SideEffectCauser() { /* code causing side-effects */ }
};
Run Code Online (Sandbox Code Playgroud)

还假设我想让一个对象为每个翻译单元创建一次这样的副作用.对于每个这样的翻译单元,我希望能够SideEffectCauser在.cpp文件中的命名空间范围内放置一个对象,例如,

SideEffectCauser dummyGlobal;
Run Code Online (Sandbox Code Playgroud)

但C++标准03 3.6.2/3表明,此对象不必在所有的构造,除非使用在.cpp文件中的对象或功能,如文章和网上的讨论,如表明,这种对象有时不会被初始化.

另一方面,有没有办法从持有类名的字符串中实例化对象?有一个声称工作的解决方案,我注意到它基于使用类型的对象,SideEffectCauser如静态数据成员,而不是全局,例如,

class Holder {
  static SideEffectHolder dummyInClass;
};

SideEffectHolder Holder::dummyInClass;
Run Code Online (Sandbox Code Playgroud)

两个dummyGlobaldummyInClass是非本地静态的,但在C++ 03标准的3.6.2/3细看表明,该通道仅适用于对象在命名空间范围.我实际上无法在C++ 03标准中找到任何内容,即当类范围内的非局部静态动态被动态初始化时,尽管9.4.2/7表明相同的规则适用于它们与命名空间中的非局部静态范围.

问题1:在C++ 03中,有没有理由相信它dummyInClass更有可能被初始化dummyGlobal?或者,如果同一翻译单元中没有使用任何功能或对象,可能都会未初始化?

问题2:C++ 11中有什么变化吗?3.6.2和9.4.2中的措辞与C++ 03版本不同,但据我所知,上面描述的场景没有指定行为差异.

问题3:是否有一种可靠的方法来使用类SideEffectHolder功能体外的类对象来强制发生副作用?

c++ c++11

28
推荐指数
1
解决办法
1371
查看次数

为什么非静态数据成员不能成为constexpr?

这是有效的代码:

struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  const int xVal { 0 };
  const int yVal { 0 };
};
Run Code Online (Sandbox Code Playgroud)

但在这里我真的想申报xVal并 - 像yVal constexpr这样:

struct S {
  constexpr S(int x, int y): xVal(x), yVal(y) {}
  constexpr S(int x): xVal(x) {}
  constexpr S() {}

  constexpr int xVal { 0 };         // error!
  constexpr int yVal { 0 };         // error!
};
Run Code Online (Sandbox Code Playgroud)

如上所示,代码将无法编译.原因是(根据7.1.5/1),只能声明静态数据成员constexpr.但 …

c++ constexpr c++11

26
推荐指数
1
解决办法
1万
查看次数

在引用限定符上重载成员函数的用例是什么?

C++ 11使得基于引用限定符重载成员函数成为可能:

class Foo {
public:
  void f() &;   // for when *this is an lvalue
  void f() &&;  // for when *this is an rvalue
};

Foo obj;
obj.f();               // calls lvalue overload
std::move(obj).f();    // calls rvalue overload
Run Code Online (Sandbox Code Playgroud)

我理解这是如何工作的,但它的用例是什么?

我看到N2819建议将标准库中的大多数赋值运算符限制为左值目标(即向赋值运算符添加" &"引用限定符),但这被拒绝了.所以这是一个潜在的用例,委员会决定不再使用它.那么,再一次,什么是合理的用例?

c++ overloading qualifiers rvalue-reference c++11

24
推荐指数
2
解决办法
3131
查看次数

std :: swap(x,x)是否保证x不变?

这个问题是基于Scott Meyers最近发表的博客文章.

看起来"显而易见" std::swap(x, x)应该x在C++ 98和C++ 11中保持不变,但我无法在任何标准中找到任何保证.C++ 98 std::swap在复制构造和复制赋值方面进行了定义,而C++ 11则根据移动构造和移动赋值来定义它,这似乎是相关的,因为在C++ 11(和C++ 14)中,17.6 .4.9表示移动分配不需要自我分配安全:

如果函数参数绑定到右值引用参数,则实现可以假定此参数是对此参数的唯一引用.... [注意:如果程序在将左值传递给库函数时将左值转换为x值(例如通过使用参数move(x)调用函数),程序实际上要求该函数将该左值视为暂时的.实现可以自由地优化别名检查,如果参数是左值,则可能需要这些检查. - 尾注]

引起这种措辞的缺陷报告使结果清晰:

这澄清了移动赋值运算符不需要执行复制赋值运算符中常见(并且需要)的传统if(this!=&rhs)测试.

但是在C++ 11和C++ 14中,std::swap预计会使用这个实现,

template<typename T>
void swap(T& lhs, T& rhs)
{
  auto temp(std::move(lhs));
  lhs = std::move(rhs);
  rhs = std::move(temp); 
}
Run Code Online (Sandbox Code Playgroud)

并且第一个赋值是对self进行赋值,其中参数是rvalue.如果移动赋值运算符T遵循标准库的策略并且不担心赋值给自己,那么这似乎可以判断未定义的行为,这也意味着它std::swap(x, x)也会具有UB.

即使是孤立的,这也是令人担忧的,但是如果我们认为std::swap(x, x)在C++ 98中应该是安全的,那么这也意味着C++ std::swap11/14可以默默地破坏C++ 98代码.

所以std::swap(x, x)保证x保持不变?在C++ 98中?在C++ 11中?如果是,那么它如何与17.6.4.9的移动分配许可相互作用而不是自我分配安全的?

c++ swap c++11

24
推荐指数
1
解决办法
1568
查看次数

是int-> double-> int保证是保值吗?

如果我有一个int,将其转换为一个double,然后转换double回的int,我保证可以得到相同的值返回,我开始?换句话说,给定此功能:

int passThroughDouble(int input)
{
  double d = input;
  return d;
}
Run Code Online (Sandbox Code Playgroud)

我能保证passThroughDouble(x) == x所有intx吗?

c++ c++11

23
推荐指数
2
解决办法
898
查看次数