小编Joh*_*ohn的帖子

`std::cout` 是如何实现的?

std::cout是 的一个实例std::ostreamstd::cout我可以在名为 的文件中看到 的声明/usr/include/c++/7/iostream

extern ostream cout;      /// Linked to standard output
Run Code Online (Sandbox Code Playgroud)

并且std::ostream由 定义typedef std::basic_ostream<char> std::ostream

更重要的是,您似乎无法创建 的实例std::ostream。请参阅此演示代码片段

#include<iostream>

int main()
{
    std::ostream os;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以下是编译器对上面代码片段的抱怨:

In file included from /opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/iostream:39:0,
                 from <source>:1:
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream: In function 'int main()':
/opt/compiler-explorer/gcc-4.9.0/include/c++/4.9.0/ostream:384:7: error: 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char; _Traits = std::char_traits<char>]' is protected
       basic_ostream()
       ^
<source>:5:18: error: within this context
     std::ostream os;
                  ^
Run Code Online (Sandbox Code Playgroud)

问题来了,既然被std::basic_ostream<_CharT, …

c++ linux

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

调用“string::c_str()”时实际上做了什么?

string::c_str()调用时实际上做了什么?

  1. string::c_str()将分配内存,复制字符串对象的内部数据并将空终止字符附加到新分配的内存中?

或者

  1. 由于必须是 O(1),因此不再允许string::c_str()分配内存并复制过来。string实际上,始终存在空终止符是唯一合理的实现。

在这个问题的答案的评论中有人说C++11 要求为尾随std::string分配额外的char'\0'. 所以看来第二种选择是可能的。

另一个人说std::string操作——例如迭代、串联和元素变异——不需要零终止符。除非您将 传递string给需要以零结尾的字符串的函数,否则可以省略它

更多来自专家的声音

为什么实现者通常让 .data() 和 .c_str() 做同样的事情?

因为这样做效率更高。使 .data() 返回非 null 终止的内容的唯一方法是让 .c_str() 或 .data() 复制其内部缓冲区,或者仅使用 2 个缓冲区。拥有一个以 null 结尾的缓冲区始终意味着您在实现 std::string 时始终可以仅使用一个内部缓冲区。

string::c_str()所以我现在真的很困惑,调用时实际上做了什么?

更新

如果c_str()实现为简单地返回指针,则它已经被分配和管理。

A。由于c_str()必须以 null 终止,因此内部缓冲区需要始终以 null 终止,即使对于空的 std::string,例如: ;的内部存储器中std::string demo_str应该有一个。我对吗?\0demo_str

B.std::string::substr()调用时会发生什么自动将 a …

c++ string stl

8
推荐指数
1
解决办法
1577
查看次数

构造函数隐式删除

下面列出了相关代码,您可以在https://godbolt.org/z/3GH8zD上查看。我确实可以解决编译器编译错误。但我并不完全清楚其背后的原因。我将不胜感激对这个问题有一些帮助。

struct A
{
    int x;
    A(int x = 1): x(x) {} // user-defined default constructor
};

struct F : public A
{
    int& ref; // reference member
    const int c; // const member
    // F::F() is implicitly defined as deleted
};

int main()
{
  F f; // compile error
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

Could not execute the program

Compiler returned: 1

Compiler stderr

<source>:10:15: error: declaration does not declare anything [-fpermissive]

   10 |         const int; // const member

      |               ^~~ …
Run Code Online (Sandbox Code Playgroud)

c++ constructor

7
推荐指数
1
解决办法
3198
查看次数

std::shared_ptr 的“自有指针”和“存储指针”有什么区别?

根据这个文档,它说(强调我的):

http://www.cplusplus.com/reference/memory/shared_ptr/owner_before/

与 operator< 重载不同,这种排序考虑了shared_ptr 拥有的指针,而不是存储的指针,如果这些对象中的两个被认为是等价的(即,无论操作数的顺序如何,此函数都返回 false),如果它们两者共享所有权,或者它们都为空,即使它们存储的指针值不同。

所述存储的指针(即,指针的shared_ptr对象解除引用到)可能不是在所有的指针(即,指针上物件破坏删除)如果对象的shared_ptr是一个别名(别名构造的对象和它们的副本)。

的“拥有的指针”和“存储的指针”有std::shared_ptr什么区别?

我将不胜感激能在这个问题上得到一些帮助。

这是一些相关代码(检查http://cpp.sh/27auqq):

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {int a; int b; };

int main () {
  std::shared_ptr<C> foo, bar;

  foo = std::make_shared<C>();

  bar = foo->shared_from_this();
  
  std::shared_ptr<int> p1(foo, &foo->a);
  std::shared_ptr<int> p2(foo, &foo->b);
  
  *p1=5;
  *p2=9;
  
  std::cout << p1.use_count() << std::endl;
  std::cout << foo->a << std::endl;
  std::cout << foo->b << std::endl;

  if (!foo.owner_before(bar) && !bar.owner_before(foo))
    std::cout …
Run Code Online (Sandbox Code Playgroud)

c++ shared-ptr c++11

7
推荐指数
2
解决办法
286
查看次数

调用指向超出范围的 lambda 的指针是否合法?

调用指向不再存在的 lambda 的指针是否合法?

这是演示代码片段

#include <iostream>

typedef int (*Func)(int a);

int main()
{
 Func fun;

 {
    auto lambda = [](int a)->int{std::cout << a << std::endl; return a;};   
    fun =lambda;
 }

 fun(6); //Is it legal? The variable lambda does not exist anymore.
}
Run Code Online (Sandbox Code Playgroud)

通用条件怎么样,比如说有捕获的 lambda?

c++ lambda c++11

6
推荐指数
1
解决办法
121
查看次数

为什么 EXECUTABLE_OUTPUT_PATH 不起作用?

我有这样的文件

.
??? CMakeLists.txt
??? src
    ??? CMakeLists.txt
    ??? main.c
Run Code Online (Sandbox Code Playgroud)

这是关于这个文件的内容

$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
PROJECT (HELLO)
ADD_SUBDIRECTORY(src bin)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/binarydir)

$ cat src/CMakeLists.txt
ADD_EXECUTABLE(hello main.c)

$ cat src/main.c
#include <stdio.h>
int main()
{
    printf("Hello World from t1 main().\n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后我使用以下命令构建它

$ mkdir build
$ cd build
$ cmake ..
$ make
Run Code Online (Sandbox Code Playgroud)

这是结果目录结构

然后二进制文件hello将在目录中build/bin作为图片生成,但它应该在,build/binarydir因为我有set的值EXECUTABLE_OUTPUT_PATH,不是吗?我错过了什么?

c++ build cmake

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

为什么“weak.lock()”返回“nullptr”,定义为“auto weak=std::make_shared&lt;int&gt;(42);”?

为什么在这段代码片段中weak.lock()返回nullptr

   std::weak_ptr<int> weakPtr1 = std::make_shared<int>(6);
   std::cout << weakPtr1.lock() << std::endl;
Run Code Online (Sandbox Code Playgroud)

而它在以下情况下工作:

   std::shared_ptr<int> sharedPtr = std::make_shared<int>(99);
   std::weak_ptr<int> weakPtr2 = sharedPtr;
   std::cout << weakPtr2.lock() << std::endl;
Run Code Online (Sandbox Code Playgroud)

检查 cpp.sh/9gkys。

我曾经想过,想过,但我现在仍然很困惑。我将不胜感激能在这个问题上得到一些帮助。

c++ smart-pointers

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

将派生类标记为可移动而基类不可移动是否有意义\适合吗?

将派生类标记为可移动而基类不可移动是否有意义\适合吗?

我知道这种不一致在 C++ 中是合法的,但它在实践中有意义\适合吗?

一般来说,我应该刻意保持这种一致性吗?

这种情况怎么样:当我打算将派生类标记为不可移动和不可复制时,我是否也应该将基类标记为不可移动和不可复制?

我做了几次测试才清楚。

这是第一个例子。由于基类是不可复制和不可移动的,因此派生类实际上是不可移动的,因为它有一个移动构造函数,这在我的期望中。提示:下面的代码片段无法编译。

#include <memory>
#include <string>
#include <iostream>

class Base {
public:
    Base(){}
    Base(const Base&) = delete;
    Base(Base&&)      = delete;
    Base& operator=(const Base&) = delete;
    Base& operator=(Base&&) = delete;
};

class Derived:public Base
{
public:
    Derived(){}
    Derived(const Derived&) = default;
    Derived(Derived&&)      = default;
    Derived& operator=(const Derived&) = default;
    Derived& operator=(Derived&&) = default;
};

int main()
{
    Derived derived;

    Derived derived1{std::move(derived)};
}
Run Code Online (Sandbox Code Playgroud)

这是第二个例子。基类是可复制且不可移动的,但派生类实际上是可移动的,因为在调用派生类的移动构造函数时,它会调用基类的复制构造函数,而不是基类的移动构造函数,即也在我的预料之中。提示:下面的代码片段效果很好。

#include …
Run Code Online (Sandbox Code Playgroud)

c++ constructor copy-constructor move-constructor c++11

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

为什么 template&lt;classTp&gt; bool is_array&lt;Tp[]&gt; 是 template&lt;class T&gt; bool is_array&lt;Tp&gt; 的部分特化?

如何理解这template<typename Tp> bool is_array<Tp[]> = true是对 的部分专业化template<typename T> bool is_array<Tp> = true

这是相关的代码片段:

#include<iostream>

template<typename T>
bool is_array = false;

template<typename Tp>
bool is_array<Tp[]> = true;

int main()
{
    std::cout << is_array<int> << std::endl;
    std::cout << is_array<int[]> << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我还注意到,一般来说,部分模板特化中的模板参数数量少于主模板中的模板参数数量。

部分专业化通常是这样的

#include<iostream>

template<typename T, typename U>
class add
{
public:
    add(T x, U y)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};

template<typename U>
class add<int, U>
{
    public:
    add(int x, U …
Run Code Online (Sandbox Code Playgroud)

c++ templates template-specialization

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

在实践中,什么时候必须使用“std::unordered_map”而不是“std::map”?

实际应用中,有什么情况std::unordered_map必须用 来代替std::map

我知道它们之间的区别,比如内部实现、搜索元素的时间复杂度等等。

但我实在找不到确实std::unordered_map可以替代的情况std::map

c++ stl unordered-map stdmap

4
推荐指数
2
解决办法
598
查看次数