我正在学习 C++ 中的继承。我发现了以下声明:
换句话说,this 指针不能在构造函数中使用别名:
extern struct D d;
struct D
{
D(int a) : a(a), b(d.a) {} // b(a) or b(this->a) would be correct
int a, b;
};
D d = D(1); // because b(d.a) did not obtain a through this, d.b is now unspecified
Run Code Online (Sandbox Code Playgroud)
上面的例子来自cppreference。
我的第一个问题是,它写道“this不能在 ctor 中使用别名”,但在上面的示例中,他们在注释中写道“b(this->a)将是正确的”。这对我来说似乎是矛盾的,因为当他们说this不能在 ctor 中使用别名时,我理解“this不能在 ctor 中使用”。但为什么他们说如果不能在 actor 中使用/别名,那么书写b(this->a)就是正确的。this初始化列表不被认为是“在一个ctor中”吗?
现在让我们看一个自定义示例:
struct Name
{ …Run Code Online (Sandbox Code Playgroud) pow() 函数给出非常奇怪的输出。
我尝试了各种组合:
#include<stdio.h>
#include<math.h>
int main()
{
int d=1;
long long n1,n2;
while(d<10)
{
n1=pow(10,d);
n2=pow(10,d);
d++;
printf("%lld %lld\n",n1,n2);
}
}
Run Code Online (Sandbox Code Playgroud)
这给出了错误的输出,即 99 而不是 100 之类的。
现在,如果我删除其中一个变量,ans。是正确的。如果我使用常量而不是 d,则 ans 是正确的。如果我将 n1 和 n2 作为双精度,则 ans 是正确的。
因此,拥有两个 pow() 函数,并且将变量作为幂并将类型转换为整数会产生错误的输出。为什么有这种奇怪的行为?
我正在尝试学习如何在 C++ 中评估表达式。所以尝试并阅读不同的例子。下面是我无法理解它是否会产生未定义行为的代码。代码来自这里。所以我猜既然他们已经用过它了,这一定不是UB。但我有疑问。
#include <iostream>
int main()
{
int n = 1;
//std::cout << n << " " << ++n << std::endl;//this is undefined behavior i am sure
int m = (++n, std::cout << "n = " << n << '\n', ++n, 2*n);//will this also produce UB because here also we have cout in the same manner as above?
std::cout << "m = " << (++m, m) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的,我确信该声明:
cout << n << " " << …Run Code Online (Sandbox Code Playgroud) 我正在学习 C++ 中的模板。特别是,我在这里看到我们可以对构造函数进行以下声明:
template<typename T>
struct Rational
{
Rational<T>();
};
Run Code Online (Sandbox Code Playgroud)
但上面的代码片段在 C++2a 中编译失败,在 C++17 中编译成功。
这是编译器错误还是有原因导致它无法针对 C++2a 和 C++2b 进行编译。如果有原因的话,那是什么原因呢?我想知道标准中的哪些子句(如果有)允许/阻止以下示例进行编译。由于我已经使用 C++17 和 C++20 测试了上面的示例,因此我只寻找这两个标准版本的引用。
我正在学习std::vectorC++。我了解到aconst std::vector<int>意味着我们不能更改该向量中的各个元素,也不能向其中追加/推回更多元素,即我们只能对元素进行读取访问,这是 a 实体所期望的const。const std::vector但我发现定义 a与定义其他const类型(如等)时有所不同int。double情况如下所示:
int main()
{
const int i; //doesn't compiler as expected: initializer needed here
const std::vector<int> vec1 ; //COMPILES FINE: WHY ISN'T AN INITIALIZER NEEDED HERE?
}
Run Code Online (Sandbox Code Playgroud)
正如我们所看到的,对于const内置类型(例如int),我们必须提供一个初始值设定项。
我的第一个问题是,为什么std::vector. 也就是说,我们如何(为什么)可以省略const vector. 我的意思const vector是我们将无法向其中添加元素,因此vec1现在看来这(实际上)毫无用处。
所以我的第二个问题是有用途vec1吗?我的意思是,由于标准允许这样做,所以他们可能已经考虑过这种情况,并发现这vec1在某些地方可能有用。也就是说,vec1在定义时没有初始化程序的用例有哪些。
当我注意到一种这样的情况(如下所示)在 clang 和 msvc 中编译良好但在 gcc 中编译失败时,我试图显式地专门化一个成员函数模板。这是验证相同内容的链接:https ://godbolt.org/z/15z4nT5Kx
struct C
{
template<typename T>
void f()
{
}
template<> void f<int>()
{
}
};
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从上面的链接中可以看出,clang 和 msvc 编译程序没有任何问题,但 gcc 说:
<source>:10:14: error: explicit specialization in non-namespace scope 'struct C'
10 | template<> void f<int>()
| ^
<source>:10:21: error: template-id 'f<int>' in declaration of primary template
10 | template<> void f<int>()
| ^~~~~~
Run Code Online (Sandbox Code Playgroud)
这里是哪个编译器?
我知道SO上有很多类似的问题。在称其为重复之前请仔细阅读。如果是的话,我很乐意获得相关问题的参考。
在我看来,clang 消毒程序正在抱怨无符号数字的完全有效的左移。
int main()
{
unsigned int x = 0x12345678;
x = x << 12;
return 15 & x;
}
Run Code Online (Sandbox Code Playgroud)
编译如下:
clang -fsanitize=undefined,integer shift-undefined.cpp -lubsan -lstdc++
结果出现此错误:
shift-undefined.cpp:4:11: runtime error: left shift of 305419896 by 12 places cannot be represented in type 'unsigned int'
我知道有些位会被遗忘,但我认为这对于无符号数字是合法的。是什么赋予了?
修改复制构造函数的“ explicit ”关键字可能会导致问题。\n作为函数参数传递的对象特别容易受到这些问题的影响。
\n这是我的代码:
\n#include <iostream>\n#include <string>\n\nclass Pig{\npublic:\n std::string _name;\npublic:\n Pig(std::string n) : _name(n) {}\n //~Pig() = default;\n explicit Pig(const Pig &other) {\n std::cout << "copy ctor!" << std::endl;\n this->_name = other._name;\n }\n};\n\nvoid show(Pig p) {\n std::cout << p._name << std::endl;\n}\n\nint main() {\n Pig pig{std::string("hello")};\n show(Pig{pig}); // no pass\n // show(Pig(pig)); // no pass\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n编译器版本:g++(Ubuntu 9.4.0-1ubuntu1~20.04.1)9.4.0。
\n上面提到的代码不能用c++14 或更低版本编译,\n但用c++17 及更高版本编译成功。
\n这是编译器的错误:
\ntest.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\ntest.cpp:22:7: error: cannot …Run Code Online (Sandbox Code Playgroud) 我正在使用 Stanley 的《C++ Primer》一书学习 C++。特别是,关于“指针转换”的部分说:
指向任何非常量类型的指针都可以转换为
void*
读完本文后,我编写了以下程序,该程序使用 msvc 进行编译,没有任何诊断,但被 gcc 和 clang 拒绝。演示
int func()
{
return 4;
}
int main()
{
void* ptr = &func; //works with msvc but rejected by clang and gcc
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,上面的程序适用于 msvc,但 gcc 说error: invalid conversion from 'int (*)()' to 'void*'。
我想知道哪个编译器在这里是正确的。请注意,我已将/permissive-flag 与 msvc 一起使用以使其符合标准。
c++ pointers function-pointers language-lawyer pointer-conversion
来自C++标准工作草案:
默认构造函数 ([class.default.ctor])、复制构造函数、移动构造函数 ([class.copy.ctor])、复制赋值运算符、移动赋值运算符 ([class.copy.assign]) 和预期析构函数 ([class .dtor])是特殊成员函数。
(https://eel.is/c++draft/special)
给出以下代码:
struct S {
S(int, float, double);
};
Run Code Online (Sandbox Code Playgroud)
在我的理解中, 的构造函数S不是特殊的成员函数,因为它既不是默认构造函数,也不是复制构造函数,也不是移动构造函数。
我想知道标准是否仍然认为构造函数是成员函数(或“唯一”的东西)。
我阅读了 C++ 工作草案中有关成员函数、特殊成员函数和构造函数的部分,但没有找到任何合理的答案来回答这个问题。我还查看了 StackOverflow,但大多数答案都指出所有构造函数都被视为特殊成员函数,这似乎与标准相矛盾。