关于oop:C ++属性声明

C++ property declaration

本问题已经有最佳答案,请猛点这里访问。

我正在深入研究来自ObjuleC和Java世界的C++。Java给了我所有的OOP知识,我和Objul-C教了我关于手动内存管理。虽然适应C++是很容易的(语言绝对不值得拥有它的名声)我对一件事感到困惑:

我可以宣布财产为string my_stringstring *my_string。我知道我需要删除第二个,但是把它声明为指针有什么好处呢?


人们的回答几乎是完全的,但我要补充一个原因:虽然将变量声明为指针是无用的,但是如果它是一个大结构,并且您必须将它作为参数传递给许多函数(如递归算法),那么它就非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
strcut sMyStruct
{
   // A lot of members
}

// Somewhere in your code
sMyStruct   foo;
RecursiveOperation( &foo );

// Somewhere else if you want foo to don't be modified.
void RecursiveOperation( const sMyStruct *pFoo )
{
}
// or...
void RecursiveOperation( sMyStruct *pFoo )
{
}

在这种情况下,使用*pfoo可以使代码更快、更便宜,即使您可以使用&;来传递引用,但其安全性更高,但速度稍慢。很明显我可能是错的,但这是同事们教我的。


在大多数情况下,使用指针变量根本没有好处。

使用此方法的一个原因是,如果希望成员在对象被破坏后仍然存在(如果不在析构函数中删除它)。然而,这种必要性通常是由糟糕的设计强制执行的,所以我会尽量避免这种情况。

另一个原因(更可能的原因)是,如果您希望成员可以是未定义的(即,在构造函数中将成员初始化为NUL/NULLPTR(C++ 11),并且每个读取访问检查指针是否仍然为空或实际指向值)。这样可以推迟初始化。但是,即使在这种情况下,我也建议使用智能指针(STD:C++中的SydDypTR 11或Booost::ScReDypPTR在C++ 98)或Booo::可选的…


您必须了解指针是一种将地址保存到内存位置的东西,它既可以保存堆栈中的地址,也可以保存堆中的地址。


没有什么。在C++中,除非需要,否则使用指针而不是指针。实际上,在大多数情况下,您也可以使用引用而不是指针(比如函数调用)。

使用std::string*确实没有意义。

A*唯一有意义或有用的时间是,当有A的子类要分配给这个基类指针时。一个例子,经典的shape

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <memory>
#include <vector>

class shape
{
public:
  virtual ~shape() {}; // required to properly be able to delete base class pointers    
  virtual bool isRound() const = 0;
  virtual const char* name() const = 0;
};

class rectangle : public shape
{
public:
  bool isRound() const { return false; }
  const char* name() const { return"rectangle"; }
};

class circle : public shape
{
  bool isRound() const { return true; }
  const char* name() const { return"circle"; }
};

class square : public rectangle
{
  const char* name() const { return"square"; }
};

int main()
{
  std::vector<std::unique_ptr<shape>> shapes;
  shapes.emplace_back(new square());
  shapes.emplace_back(new circle());
  shapes.emplace_back(new rectangle());

  for(const auto& s : shapes)
  {
    if(s->isRound())
      std::cout << s->name() <<" is round.
"
;
    else
      std::cout << s->name() <<" is not round.
"
;
  }
}

现场演示

这里,指针的向量只是一个例子,它可能是一个类的成员,或者其他任何真正的成员。注:我用std::unique_ptr代替shape*。了解智能指针。快。


在C++中,可以将变量存储在堆栈上或堆上,当您管理指针时,通常是堆上的,需要手动内存管理。

小对象适合堆栈,大对象(如非常大的字符串)不适合堆栈,并且可能导致堆栈溢出(堆栈非常小,请参阅编译器了解堆栈空间)。

std::string不是堆栈上的大对象,因为它们在内部管理堆上的指针。将字符串声明为指针意味着您通常需要该字符串引用其他内容。

我能给你的建议是永远避免原始指针。倾向于std::unique_ptrstd::shared_ptr


I know I need to delete the second

指针并不一定意味着涉及到任何动态分配。因此指针不需要自动为deleted。

What's the advantage in declaring it as a pointer?

根据经验,您应该始终使用自动分配的内存(~堆栈)。如果您觉得有必要使用动态分配的内存(例如,在堆栈中缺乏空间),您将知道。动态分配的内存也可以用来手动控制对象的生存期,但这在大多数情况下是危险的:这就是为什么我们有像std::unique_ptrstd::shared_ptr这样的智能指针的原因。

在这种特殊情况下,除非您确实需要一个指向std::string的指针作为对字符串的引用(可以是nullptr),否则我看不到它的用途。大多数std::string的实现已经动态地存储了char数组。