我正在阅读 Bjarne Stroustrup 的《C++ 编程原理与实践》(第二版)。在第 660-661 页,作者定义了一个函数,如下所示:
istream& read_word(istream& is, char* buffer, int max)
// read at most max-1 characters from is into buffer
{
is.width(max); // read at most max-1 characters in the next >>
is >> buffer; // read whitespace-terminated word,
// add zero after the last character read into buffer
return is;
}
Run Code Online (Sandbox Code Playgroud)
稍后int main(),该函数被调用为read_word(cin,s,max);where cinis std::cin, maxis an int, and sis a chararray of size max …
这可能是一个愚蠢的问题,因为我对 C++ 中运算符的实现还很陌生......
我使用new运算符/表达式/关键字已经有一段时间了。但我刚刚注意到有一个名为 的函数operator new。据我所知,在大多数情况下,new操作符首先调用“默认”operator new为需要创建的对象分配原始内存,然后调用对象的构造函数在该内存上创建对象。我们可以operator new在全局范围或类中覆盖默认值。
我想知道(默认)operator new是在哪里定义的。一方面,我认为它没有在 中定义std,因为如果我这样做:
std::operator new(42);
Run Code Online (Sandbox Code Playgroud)
视觉工作室说namespace "std" has no member "operator new"。此外,operator new(42);当我既不包含任何标准标头也不包含using namespace std;.
另一方面,我发现如果我这样做:
include <iostream>
int main() { operator new(42); }
Run Code Online (Sandbox Code Playgroud)
Visual Studio 然后告诉我operator new我正在使用的内容如下:
_NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR
void* __CRTDECL operator new(
size_t _Size
);
Run Code Online (Sandbox Code Playgroud)
它在vcruntime_new.h( 又由included <new>) 中声明。然而,如果我注释掉include <iostream> …
我知道声明为的函数inline必须在其自己的翻译单元中有定义(正如标准所说:内联函数应在使用它的每个翻译单元中定义)。
以前,我对这个要求的理解是,编译器会尝试内联用inline关键字声明的函数,因此虽然内联不是强制性的,但定义首先应该对编译器可见。
根据这种理解,我认为不提供定义应该会导致编译器错误。事实上,我从来没有编写过inline没有定义的函数。但后来我在我的玩具程序中故意尝试了这个错误,它导致了链接器错误。
所以,我只是好奇为什么 C++ 不将这个问题保留为编译时错误并让编译器捕获该错误?而且,根据我的理解,inline函数默认具有外部链接,因此链接器到底如何在幕后捕获此错误?
一个例子:
// main.cpp:
inline void InlineFun();
int main()
{
InlineFun();
}
// other.cpp:
#include<iostream>
#include<string>
inline void InlineFun()
{
std::cout << "From other TU" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我在 Windows 10 上使用 Visual Studio 2022 和 C++20。我遇到的错误是LNK2001 和LNK1120。评论中提供的示例也非常好。
后续示例:
// main.cpp:
inline void InlineFun();
int main()
{
InlineFun(); // From other TU
}
// other.cpp:
#include<iostream>
#include<string>
inline void InlineFun()
{
std::cout << "From …Run Code Online (Sandbox Code Playgroud) 给定
int i = 42;
int* p = &i;
Run Code Online (Sandbox Code Playgroud)
我们做不到
const int * & d = p;
Run Code Online (Sandbox Code Playgroud)
在我目前的理解中,这是因为const int * & d可以读作“d是一个指向 an 的指针的引用int,它是一个const”,并且p是“指向 an 的指针int”,这意味着 RHS 需要变成一个临时的“指向 an 的指针”。 anint是一个const" 并且不能直接与引用绑定(如在 LHS 上)。我们需要有,比如说,const int* const& d = p;。可能的参考文献:1、2。
也就是说,请考虑以下玩具代码:
template<typename T>
class X
{
public:
void fun(const T& d) { }
};
Run Code Online (Sandbox Code Playgroud)
起初我想如果我这样做
X<int*> x;
x.fun(p); …Run Code Online (Sandbox Code Playgroud) 给出以下玩具代码:
class X
{
public:
X() { }
X(const X&) { }
//X(X&&) = delete;
};
int main()
{
X x;
X y = std::move(x);
}
Run Code Online (Sandbox Code Playgroud)
我知道X::X(X&&)在这种情况下它被隐式删除,因为它X(const X&)作为用户声明的构造函数存在。但我对这里术语“隐式删除”的含义有点困惑:如果我们取消注释,代码的行为会有所不同,这意味着隐式删除和“显式”删除X(X&&) = delete;之间存在差异。
我心中有两种不同的理解:
“隐式删除”意味着编译器生成一些类似于的代码X(X&&) = delete;(也就是说,编译器知道存在X(X&&)并且知道它X(X&&)被删除),但生成的代码X(X&&) = delete;在某种程度上不同于,当X y = std::move(x);尝试调用时X::X(X&&),编译器选择X(const X&)而不是报告错误。(如果X(X&&) = delete;取消注释,编译器不会选择X(const X&),会报错)
“隐式删除”意味着X(X&&)根本没有在类中声明,换句话说,编译器没有任何有关的信息X(X&&),因此X y = std::move(x);直接与 …
根据我目前的理解,粗略地说,static当执行线程离开其作用域时,(非)局部变量将被销毁。但是我发现局部变量在不同的情况下被销毁的具体点是不一样的。我一直在努力理解如何确定局部变量何时被销毁,特别是其背后的原因。(我问的可能相关问题包括:1、2、3)
给定 2 个玩具类:
class A {
public:
A() { cout << "A created\n"; }
A(const A&) { cout << "A copied\n"; }
~A() { cout << "A destroyed" << endl; }
};
class B{
public:
B() { cout << "B created\n"; }
B(const B&) { cout << "B copied\n"; }
~B() { cout << "B destroyed\n"; }
};
Run Code Online (Sandbox Code Playgroud)
B& f() {
A a;
static B b;
return b;
}
int main() …Run Code Online (Sandbox Code Playgroud) 这是我上一个问题的后续问题。
考虑以下玩具代码:
#include <iostream>
using namespace std;
class X
{
public:
X() { }
X(X&& x)
{
cout << "move ctor\n";
}
/*X(X& x)
{
cout << "copy ctor\n";
}*/
};
X f()
{
static X x;
X&& y = std::move(x);
X& z = x;
return y;
}
int main()
{
f();
}
Run Code Online (Sandbox Code Playgroud)
根据我对上一个问题(即class.copy.elision#3use of deleted function 'constexpr X::X(const X&)' )的理解,我认为这会导致上述代码中的错误( )返回y到f().
问题是,我在 PC 上的 Visual Studio 中运行代码,它编译并打印move ctor. 所以我 …