小编AnT*_*AnT的帖子

用户定义的operator new,返回空指针

我知道很少有C++常见问题解答(以及SO上的答案)说没有必要检查普通new-expression的返回值为null,因为普通的new-expression通过抛出异常来表示失败.他们基本上声明普通的new-expression永远不会返回null.(通过"普通新表达式"我的意思是一个不是一个新表达式nothrow).

然而,尽管这看起来像一个非常基本的问题,我突然意识到,当他们给出答案时,我不明白他们做出的具体假设(如果有的话).

特别是,我想知道我是否允许重载基本的普通形式::operator new以始终返回空指针,因此期望所有使用该运算符的普通新表达式现在也将返回空指针.

根据语言规范,如果我::operator new被声明为非投掷,那么我可能/将通过返回空指针来指示内存分配失败.所以,让我们这样做

void *operator new(size_t s) throw() {
  return 0;
}

int main() {
  int *i = new int;
}
Run Code Online (Sandbox Code Playgroud)

在我的实验中,上面的new-expression确实成功返回一个空指针.那么,我是否违反了上述代码中的任何规则?宣布平原::operator new为非投掷是否合法?

如果上面的代码没问题,那么我认为当有人声明一个普通的新"永不返回空指针"时,他们会假设标准库提供的版本::operator new没有被替换.这个推定是否正确?

c++ null standards-compliance new-operator

5
推荐指数
1
解决办法
1084
查看次数

传统的标准C库头文件和重载的C++函数

C++语言标准在D.5中

2每个C标头(每个标头都有一个表单名称)的name.h行为就好像每个由相应cname标头放置在标准库名称空间中的名称放在全局名称空间范围内.未指定是否首先在命名空间的命名空间范围(3.3.6)中声明或定义这些名称std,然后通过显式using-declarations(7.3.3)将这些名称注入到全局命名空间范围中.

3 [示例:标头<cstdlib> 确实在命名空间中提供其声明和定义std.它还可以在全局命名空间中提供这些名称.标题<stdlib.h>肯定在全局命名空间中提供相同的声明和定义,就像在C标准中一样.它还可以在命名空间中提供这些名称 std. - 末端的例子]

这似乎相当明确地说明了("......每个名字......","......相同的声明......")旧式<name.h>标题必须提供与新式标题相同的声明<cname>集,但在全局命名空间.例如,对于各种C函数的C++特定重载版本,没有例外.

这似乎意味着,<math.h>必须提供三个版本的sin功能:sin(float),sin(double)sin(long double)在全局命名空间.反过来,这意味着以下C++代码应该无法解决重载问题

#include <math.h>

int main() {
  sin(1);
}
Run Code Online (Sandbox Code Playgroud)

它在MSVC++编译器下失败,但它在GCC和Clang下成功编译.那么,GCC是否只是忽略了已弃用的旧式标题的标准要求?还是我以某种方式误解了标准中的措辞?

c++ legacy standard-library

5
推荐指数
1
解决办法
491
查看次数

`nextafter` 和 `nexttoward`:为什么是这个特定的界面?

这种特殊的nextafter(和nexttoward函数接口背后的原因究竟是什么?我们指定的方向通过指定我们想要移动的价值走向

乍一看,这个想法背后似乎隐藏着一些不明显的东西。在我(天真)看来,此类函数的首选将类似于一对单参数函数nextafter(a)/ nextbefore(a)。下一个选择将是一个双参数函数nextafter(a, dir),其中dir明确指定方向(-1+1,一些标准枚举等)。

而是我们必须指定一个,我们希望移动走向。因此有许多问题

  1. (一个模糊的)。可能有一些聪明的想法或惯用的模式非常有价值,以至于影响了这些标准功能中的接口选择。在那儿?

  2. 如果决定盲目地使用-DBL_MAX+DBL_MAX作为nextafter分别指定负方向和正方向的第二个参数会怎样。这样做有什么陷阱吗?

  3. (2 的改进)。如果我知道肯定b是[轻微]大于a,没有任何理由,更喜欢nextafter(a, b)nextafter(a, DBL_MAX)?例如,nextafter(a, b)版本是否有更好的性能?

  4. nextafter通常一个沉重的操作?我知道它是依赖于实现的。但是,再次假设一个基于 IEEE 754 表示的实现,找到相邻的浮点值是否相当“困难”?

c floating-point standard-library

5
推荐指数
1
解决办法
239
查看次数

从非实例化的上下文中引用特定的模板特化:实例化与否?

请考虑以下示例

template <typename A> struct S 
{
  A a;
  void foo() {}
};  

template <typename T> void bar()
{
  S<void> *p = 0;
}

template <typename T> void baz()
{
  S<void>{}.foo();
}

template <typename T> void qux()
{
  S<void> s{};
}

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

功能模板bar,bazqux故意留下非实例化.

由于baz"明显"的原因,未能在GCC和Clang中编译的定义S<void>是无效的专业化S.但是,在这种情况下,哪种语言规则正在起作用?

  1. 一方面,S<void>不依赖于模板参数baz,成员访问要求它完成,从而触发实例化S<void>,失败.诊断是必需的.

  2. 另一方面,我们有一条全面的规则:"如果没有为非实例化的模板生成有效的专业化,则代码就是格式错误".这使得baz形成不良的定义.但是,不需要诊断.

更具体地说,我是否正确地假设(如#1所述)上述S<void>非实例baz化的引用需要实例化S<void>?两个编译器都乐于接受bar未实例化的定义这一事实支持了这一假设S<void>. …

c++ templates template-specialization language-lawyer template-instantiation

5
推荐指数
1
解决办法
72
查看次数

"void""对象"的非定义声明:C++标准的哪一部分禁止它们?或者是吗?

有在C++标准至少两个地方禁止限定对象与不完全类型(http://eel.is/c++draft/basic.def#5,http://eel.is/c++draft/basic .types#5).但是,在C++中通常允许为不完整类型的对象提供非定义声明.而且我似乎无法确定那些禁止void以这种方式声明类型不完整的"对象"的特定部分.(当然,void在一个例子中,它不是C++中的对象类型,但它们都不是引用类型.)所以,就是这样

extern void a;
Run Code Online (Sandbox Code Playgroud)

在C++中真的不合格?

在C void中,允许对象的非定义声明(如上所示),GCC和Clang都接受C代码中的上述内容(当然不允许定义).但在C++代码中,两个编译器都会为此类声明发出错误.标准的哪一部分让他们这样做?

[basic.fundamental]列出了void类型的可能用途(http://eel.is/c++draft/basic.types#basic.fundamental-13),但它似乎并不是一个完整的列表.

c++ declaration void language-lawyer incomplete-type

5
推荐指数
1
解决办法
155
查看次数

对未知大小数组的引用的列表初始化:是否应该推断出数组大小?

以下代码在Clang中编译良好,并输出int [3]数组的大小

#include <iostream>

int main()
{
  const int (&a)[] = { 1, 2, 3 };
  std::cout << sizeof a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但是,在GCC中,该声明可以很好地编译,但sizeof a不能编译:显然,GCC拒绝“推导”数组大小,最终a以引用const int []类型的方式结束,这是不完整的。

这种初始化的预期行为是什么?

在这种情况下,9.3.4 / 3似乎是标准的相关部分,但就其本身而言,似乎并不能得出结论。

c++ arrays reference list-initialization

5
推荐指数
1
解决办法
115
查看次数

带有大小参数和不带大小参数的“操作员删除”:当两者都可用时,选择哪个?

当我在GCC和Clang中运行此代码示例时

struct S
{
  int a;        

  void *operator new(size_t s) 
  { 
    std::cout << "new " << s << std::endl;
    return ::operator new(s); 
  }

  void operator delete(void *p, size_t s) noexcept 
  { 
    std::cout << "delete " << s << std::endl;
    ::operator delete(p);
  }

  void operator delete(void *p) noexcept
  { 
    std::cout << "delete " << "none" << std::endl;
    ::operator delete(p);
  }
};

int main()
{
  S *p = new S;
  delete p;
}
Run Code Online (Sandbox Code Playgroud)

我从GCC和Clang得到以下输出

new 4
delete none
Run Code Online (Sandbox Code Playgroud)

这意味着编译器选择的“无尺寸”版本operator delete。 …

c++ operator-overloading language-lawyer delete-operator c++14

5
推荐指数
1
解决办法
95
查看次数

通过memcpy将unsigned char数组转换为unsigned int返回unsigned char数组是相反的

这不是跨平台代码......一切都在同一平台上执行(即endianess是相同的..小端).

我有这个代码:


    unsigned char array[4] = {'t', 'e', 's', 't'};
unsigned int out = ((array[0]<<24)|(array[1]<<16)|(array[2]<<8)|(array[3])); std::cout << out << std::endl;
unsigned char buff[4]; memcpy(buff, &out, sizeof(unsigned int));
std::cout << buff << std::endl;

我希望buff的输出是"test"(由于缺少'/ 0'而带有垃圾尾随字符),而输出是"tset".显然改变我正在移动的字符顺序(3,2,1,0而不是0,1,2,3)解决了问题,但我不明白这个问题.memcpy不按我期望的方式行事吗?

谢谢.

c c++

4
推荐指数
1
解决办法
4294
查看次数

C++:模板分配操作符重载的编译错误

当我在VC++ 6中编译以下代码时,我不断收到错误"使用类模板需要模板参数列表".这有什么问题?

template <class T>  
class StdVector{  
    public:                 
        StdVector & operator=(const StdVector &v);
};

template <typename T>  
StdVector & StdVector<T>::operator=(const StdVector &v){  
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

c++

3
推荐指数
1
解决办法
1197
查看次数

ccw算法说明

我在理解 ccw(逆时针)算法时遇到了一些麻烦:

int ccw (Point P0, Point P1, Point P2) {
    dx1 = P1.x - P0.x;
    dx2 = P2.x - P0.x;
    dy1 = P1.y - P0.y;
    dy2 = P1.y - P0.y;

    if (dy1 * dx2 > dy2 * dx1) return -1;
    if (dx1 * dy2 > dy1 * dx2) return 1;
    if ((dx1 * dx2 < 0) || (dy1 * dy2 < 0)) return 1;
    if ((dx1 * dx1 + dy1 * dy1) < (dx2 * dx2 + dy2 * …
Run Code Online (Sandbox Code Playgroud)

c++ ccw

3
推荐指数
1
解决办法
3792
查看次数